<?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: Prabhu R</title>
    <description>The latest articles on DEV Community by Prabhu R (@rprabhu).</description>
    <link>https://dev.to/rprabhu</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%2F426236%2Fb9acb574-cc34-49cc-a1a6-8c2b34cc9c79.jpeg</url>
      <title>DEV Community: Prabhu R</title>
      <link>https://dev.to/rprabhu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rprabhu"/>
    <language>en</language>
    <item>
      <title>AsciidocFX: The Asciidoc Editor for documentation and authoring</title>
      <dc:creator>Prabhu R</dc:creator>
      <pubDate>Fri, 03 May 2024 06:00:00 +0000</pubDate>
      <link>https://dev.to/rprabhu/asciidocfx-the-asciidoc-editor-for-documentation-and-authoring-3dee</link>
      <guid>https://dev.to/rprabhu/asciidocfx-the-asciidoc-editor-for-documentation-and-authoring-3dee</guid>
      <description>&lt;p&gt;For those who work extensively with Asciidoc files, having a robust and feature-rich editing tool is essential. We have already see the power of Asciidoc and Asciidoctor in our previous articles as &lt;a href="https://blog.teamnexus.in/blog/2022/06/03/asciidoctor-a-writers-swiss-army-knife/"&gt;a writer's tool&lt;/a&gt; and &lt;a href="https://blog.teamnexus.in/blog/2022/06/07/stunning-presentations-with-asciidoctor-and-revealjs/"&gt;a presentation tool&lt;/a&gt;. In this article we will explore about &lt;a href="https://asciidocfx.com/"&gt;AsciidocFX&lt;/a&gt;, an open-source toolset for creating and publishing technical documentation using AsciiDoc format is a free&lt;/p&gt;

&lt;p&gt;&lt;a href="https://asciidocfx.com/"&gt;AsciidocFX&lt;/a&gt;, is an open-source, cross-platform editor that provides an exceptional user experience and a comprehensive set of features for working with Asciidoc files. Though &lt;a href="https://asciidoctor.org"&gt;Asciidoctor&lt;/a&gt; provides these capabilities, not everyone will be comfortable enough to work in the commandline or shell setting that's where AsciidocFX comes to the rescue. Let's explore some of the key capabilities that make AsciidocFX stand out.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Live real-time previewing:&lt;/strong&gt; While writing documents, authors can use live previewing to see the results of their changes immediately. This enables the user to quickly see how the final document is going to appear and reducing the time spent on compiling and reviewing documents.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-format output:&lt;/strong&gt; AsciidocFX allows generating various document formats such as HTML, PDF, EPUB, Mobi and DocBook based on your needs. This flexibility ensures that the documentation can be consumed in different contexts, catering to a diverse audience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Epub Viewer:&lt;/strong&gt; AsciidocFX provides an epub viewer, this allows the authors to view how the content appears as an epub book. However, this is rendered in a browser and not natively within AsciidocFX&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Additional functionality through extensions:&lt;/strong&gt; AsciidocFX offers advanced formatting features such as UML Diagrams, Sequence Diagrams, Mathematical Notations, File Tree representations etc through extensions that enables users to create rich and visually appealing documentation. Following is the list of popular tools supported through extensions. There are other tools that are supported by &lt;a href="https://docs.asciidoctor.org/diagram-extension/latest/"&gt;asciidoctor-diagram&lt;/a&gt; that is supported by AsciidocFX as well, however those tools are required to be in the &lt;code&gt;PATH&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.plantuml.com/"&gt;PlantUML Diagram&lt;/a&gt; - Sequence diagram, Usecase diagram,Class diagram, Activity diagram etc.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mermaid.js.org/"&gt;Mermaid Diagram&lt;/a&gt; - Create diagrams using text and code&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ditaa.sourceforge.net/"&gt;Ditaa Diagrams&lt;/a&gt; - Convert diagrams drawn in ascii art to bitmap graphics.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.mathjax.org/"&gt;MathJax&lt;/a&gt; - Mathematical Notations expressed using Tex or MathML&lt;/li&gt;
&lt;li&gt;Charts - Using JavaFX Charts Extenstion&lt;/li&gt;
&lt;li&gt;File Tree - Display file tree using a text description&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Presentation Slides:&lt;/strong&gt; AsciidocFX provides the feature to create slides using Asciidoc like how &lt;a href="https://blog.teamnexus.in/blog/2022/06/07/stunning-presentations-with-asciidoctor-and-revealjs/"&gt;Asciidoctor + RevealJS&lt;/a&gt; or &lt;a href="https://blog.teamnexus.in/blog/2024/03/12/marp-a-markdown-presentation-app-that-simplifies-your-tech-talks/"&gt;Marp for Markdown&lt;/a&gt;.  With immediate preview feature, the users see the resulting slides instantaneously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integrated File Management:&lt;/strong&gt; The built-in file manager makes it easy to navigate and manage your Asciidoc files and projects. Create, open, and save files directly within the editor for a streamlined workflow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cross-Platform Compatibility:&lt;/strong&gt; Last but not the least, it is cross-platform as it is written in Java and JavaFX and is available for Windows, macOS, and Linux, AsciidocFX ensures a consistent experience across multiple platforms, making it a versatile choice for users working in diverse environments.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these great features AsciidocFX can be an indispensable tool for many use cases that includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Software Documentation&lt;/li&gt;
&lt;li&gt;Technical Writers preparing user manuals and technical documentation&lt;/li&gt;
&lt;li&gt;Authors writing books&lt;/li&gt;
&lt;li&gt;Technical materials that includes diagrams and mathematical formulae&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, AsciidocFX is a powerful and versatile toolset for creating and publishing documentation using the format. Its features facilitates producing high-quality, visually appealing documentation. By adopting AsciidocFX, users can streamline their documentation process, improve productivity, and ultimately enhance the user experience of their software or content.&lt;/p&gt;

&lt;p&gt;Give it a try!&lt;/p&gt;

</description>
      <category>asciidoctor</category>
      <category>documentation</category>
      <category>asciidoc</category>
      <category>writing</category>
    </item>
    <item>
      <title>AI/ML - LangChain4j - AiServices</title>
      <dc:creator>Prabhu R</dc:creator>
      <pubDate>Mon, 08 Apr 2024 06:00:00 +0000</pubDate>
      <link>https://dev.to/rprabhu/aiml-langchain4j-aiservices-4p2k</link>
      <guid>https://dev.to/rprabhu/aiml-langchain4j-aiservices-4p2k</guid>
      <description>&lt;p&gt;The &lt;a href="https://blog.teamnexus.in/blog/2024/03/28/ai-ml-langchain4j-chat-memory/"&gt;previous article&lt;/a&gt; our focus has been on delving into foundational elements of &lt;a href="https://docs.langchain4j.dev/"&gt;LangChain4j&lt;/a&gt; such as &lt;code&gt;ChatLanguageModel&lt;/code&gt;, &lt;code&gt;ChatMessage&lt;/code&gt;, &lt;code&gt;ChatMemory&lt;/code&gt;, and others. Working with components at this level offers great flexibility and complete control, but it comes with the added burden of writing extensive boilerplate code. LLM-driven applications typically necessitate a multitude of interconnected components rather than a single component. Those components includes prompt templates, chat memory, LLMs, output parsers, RAG components: embedding models and stores. It frequently involves numerous interactions between these components and coordinating them all becomes an intricate and laborious task.&lt;/p&gt;

&lt;p&gt;LangChain4j aims to simplify the development process by allowing the developers to concentrate on the core business logic without getting bogged down in intricate implementation details. To achieve this, LangChain4j provides two essential high-level abstractions: &lt;code&gt;AiServices&lt;/code&gt; and &lt;code&gt;Chains&lt;/code&gt;. These concepts are designed to streamline the workflow, enables to leverage the power of AI effectively while minimizing the complexity of low-level operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  AiServices and Chains
&lt;/h2&gt;

&lt;h3&gt;
  
  
  AiServices
&lt;/h3&gt;

&lt;p&gt;LangChain4j introduces a novel approach called &lt;code&gt;AiServices&lt;/code&gt;, tailored specifically for the Java ecosystem. The primary objective of AI Services is to abstract away the complexities associated with interacting with Large Language Models (LLMs) and other components, providing a simple and intuitive API.&lt;/p&gt;

&lt;p&gt;This approach draws inspiration from popular frameworks like Spring Data JPA and Retrofit, where developers can declaratively define an interface representing the desired API, and LangChain4j automatically generates an object (proxy) that implements this interface. &lt;code&gt;AiServices&lt;/code&gt; can be perceived as a component within the service layer of the application, designed to provide AI-powered services, hence the name.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AiServices&lt;/code&gt; streamline common operations such as formatting inputs for LLMs and parsing outputs from LLMs. Furthermore, they support advanced features like chat memory, tools (Function Calling), and Retrieval-Augmented Generation (RAG).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AiServices&lt;/code&gt; can be leveraged to build stateful interactive applications that facilitate back-and-forth interactions, as well as to automate processes where each call to the LLM is isolated and self-contained. This versatility empowers developers to harness the power of AI in a seamless and efficient manner, without the need to delve into low-level implementation details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chains
&lt;/h3&gt;

&lt;p&gt;LangChain4j also offers another composable approach called &lt;code&gt;Chains&lt;/code&gt;. The concept of Chains originates from &lt;a href="https://python.langchain.com/"&gt;Python's LangChain&lt;/a&gt;. &lt;code&gt;Chains&lt;/code&gt; combine multiple low-level components and orchestrate the interactions between them, enabling the creation of more complex and customized workflows.&lt;/p&gt;

&lt;p&gt;However, one potential drawback of &lt;code&gt;Chains&lt;/code&gt; is their inherent rigidity, which can pose challenges when customization is required. Currently, LangChain4j has implemented only two types of Chains: &lt;code&gt;ConversationalChain&lt;/code&gt; and &lt;code&gt;ConversationalRetrievalChain&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ConversationalChain&lt;/code&gt; facilitates back-and-forth conversations with an LLM, maintaining context and memory across multiple interactions. On the other hand, the &lt;code&gt;ConversationalRetrievalChain&lt;/code&gt; extends this functionality by incorporating a retrieval component (&lt;code&gt;ContentRetriever&lt;/code&gt;), allowing the LLM to access and leverage external data sources during the conversation.&lt;/p&gt;

&lt;p&gt;LangChain4J recommends using the &lt;code&gt;AiServices&lt;/code&gt; instead of &lt;code&gt;Chains&lt;/code&gt; as it is more flexible, declarative and provides a simple API.&lt;/p&gt;

&lt;p&gt;In this article, we will see various examples of using &lt;code&gt;AiServices&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;First let's see a basic AiServices examples&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j:0.29.1&lt;/span&gt;
&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j-ollama:0.29.1&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.Console&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.Duration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Set&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.memory.ChatMemory&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.memory.chat.MessageWindowChatMemory&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.chat.ChatLanguageModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.ollama.OllamaChatModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.service.AiServices&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AiServicesBasic&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"mistral"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://localhost:11434"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ChatMinion&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;ChatLanguageModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OllamaChatModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;BASE_URL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MODEL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;ChatMemory&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageWindowChatMemory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withMaxMessages&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;ChatMinion&lt;/span&gt; &lt;span class="n"&gt;minion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AiServices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ChatMinion&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chatLanguageModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chatMemory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Console&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;console&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n\nPlease enter your question: "&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"exit"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"quit"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;minion&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n\nPlease enter your question: "&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We define the simple interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ChatMinion&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next come the low-level components &lt;code&gt;ChatLanguageModel&lt;/code&gt; and &lt;code&gt;ChatMemory&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ChatLanguageModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OllamaChatModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;BASE_URL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MODEL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;ChatMemory&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageWindowChatMemory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withMaxMessages&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, create the &lt;code&gt;AiServices&lt;/code&gt; object using the low-level components we created above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ChatMinion&lt;/span&gt; &lt;span class="n"&gt;minion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AiServices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ChatMinion&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chatLanguageModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chatMemory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LangChain4j's &lt;code&gt;AiServices&lt;/code&gt; utility enables creating the proxy objects that implement custom interfaces defined (&lt;code&gt;ChatMinion&lt;/code&gt; in this case). &lt;code&gt;AiServices&lt;/code&gt; should be provided the &lt;code&gt;Class&lt;/code&gt; of the interface along with the low-level components to be integrated (&lt;code&gt;ChatLanguageModel&lt;/code&gt; and &lt;code&gt;ChatMemory&lt;/code&gt;). &lt;code&gt;AiServices&lt;/code&gt; then generates a proxy object that implements this interface using reflection.&lt;/p&gt;

&lt;p&gt;This proxy object handles the necessary conversions for inputs and outputs, abstracting away the complexities of working with low-level components. Here the &lt;code&gt;ChatMinion&lt;/code&gt; interface has a &lt;code&gt;chat&lt;/code&gt; method that accepts a &lt;code&gt;String&lt;/code&gt; as input. However, the underlying &lt;code&gt;ChatLanguageModel&lt;/code&gt; component expects a &lt;code&gt;ChatMessage&lt;/code&gt; object as input. In this scenario, &lt;code&gt;AiServices&lt;/code&gt; will automatically convert the &lt;code&gt;String&lt;/code&gt; input into a &lt;code&gt;UserMessage&lt;/code&gt; before invoking the &lt;code&gt;ChatLanguageModel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Similarly, when the &lt;code&gt;ChatLanguageModel&lt;/code&gt; returns an &lt;code&gt;AiMessage&lt;/code&gt;, &lt;code&gt;AiServices&lt;/code&gt; will convert it into a &lt;code&gt;String&lt;/code&gt; before returning the result from the &lt;code&gt;chat&lt;/code&gt; method. This seamless conversion process allows working with familiar data types in the application code, while &lt;code&gt;AiServices&lt;/code&gt; handles the underlying transformations and interactions with the low-level components transparently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;minion&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To execute the statement above, &lt;code&gt;AiServices&lt;/code&gt; does the heavylifting just described. &lt;/p&gt;

&lt;p&gt;The next code example is the stream version of the &lt;code&gt;AiServices&lt;/code&gt; where the responses are streamed unlike the previous one.&lt;/p&gt;

&lt;p&gt;One additional point to note is that the LLM responds in a sarcastic tone! That is achieved using the &lt;code&gt;SystemMessage&lt;/code&gt; annotation. &lt;code&gt;AiServices&lt;/code&gt; takes care of passing the &lt;code&gt;SystemMessage&lt;/code&gt; to the LLM&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ChatMinion&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@SystemMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Answer in a sarcastic tone."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;TokenStream&lt;/span&gt; &lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the full code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j:0.29.1&lt;/span&gt;
&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j-ollama:0.29.1&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.Console&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.Duration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Set&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.data.message.AiMessage&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.memory.ChatMemory&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.memory.chat.MessageWindowChatMemory&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.chat.StreamingChatLanguageModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.ollama.OllamaStreamingChatModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.output.Response&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.service.AiServices&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.service.SystemMessage&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.service.TokenStream&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AiServicesStream&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"mistral"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://localhost:11434"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ChatMinion&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;@SystemMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Answer in a sarcastic tone."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;TokenStream&lt;/span&gt; &lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;StreamingChatLanguageModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OllamaStreamingChatModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;BASE_URL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MODEL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;ChatMemory&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageWindowChatMemory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withMaxMessages&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;ChatMinion&lt;/span&gt; &lt;span class="n"&gt;minion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AiServices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ChatMinion&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;streamingChatLanguageModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chatMemory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Console&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;console&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n\nPlease enter your question: "&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"exit"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"quit"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;future&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
            &lt;span class="nc"&gt;TokenStream&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;minion&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onNext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onComplete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="o"&gt;})&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;completeExceptionally&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="o"&gt;})&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n\nPlease enter your question: "&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sample input and output for the above&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please enter your question: Hello my name is Kevin

Oh, hello there! I'm just the most interesting person you'll ever meet. 
You know, I have a pet unicorn that I ride to work every day. 
And I can solve a Rubik's cube in under 5 seconds, no big deal. 
So, what's your superpower? Oh wait, you don't have one? 
Well, I guess we'll just have to be impressed by my extraordinary abilities then.

Please enter your question: What is my name?

Oh, right! I almost forgot. 
Your name is... oh, who am I kidding? 
It doesn't matter what your name is. 
I bet you're still more boring than a snail's race. 
But hey, keep trying to impress me with your mundane existence! 
It's always a good laugh.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the current examples have focused on text-based interactions with Large Language Models (LLMs), the power of &lt;code&gt;AiServices&lt;/code&gt; extends far beyond handling plain text data. &lt;code&gt;AiServices&lt;/code&gt; can leverage the capabilities of LLMs to work with various types of structured data, such as Plain Old Java Objects (POJOs), Collection classes, and more.&lt;/p&gt;

&lt;p&gt;By leveraging the versatility of LLMs, &lt;code&gt;AiServices&lt;/code&gt; can seamlessly convert structured data objects into a format suitable for the LLM, process the data, and then convert the LLM's output back into the desired structured data format. This powerful feature enables developers to harness the power of LLMs for a wide range of tasks involving structured data, such as data processing, analysis, transformation, and generation.&lt;/p&gt;

&lt;p&gt;For instance, you could define an interface that accepts or returns a POJO representing a complex data structure, and &lt;code&gt;AiServices&lt;/code&gt; will handle the conversion between the POJO and the LLM's input/output format transparently. Similarly, you could work with Collection classes like Lists or Maps, allowing the LLM to process and manipulate the data within these collections.&lt;/p&gt;

&lt;p&gt;This capability opens up numerous possibilities for integrating LLMs into various domains and applications, extending their utility beyond pure text-based tasks. With &lt;code&gt;AiServices&lt;/code&gt;, you can leverage the power of LLMs to process and manipulate structured data in a seamless and intuitive manner, without being constrained by the limitations of traditional text-based interfaces.&lt;/p&gt;

&lt;p&gt;In the following examples, let's build a crude profanity filter in the text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j:0.29.1&lt;/span&gt;
&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j-open-ai:0.29.1&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Map&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.chat.ChatLanguageModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.openai.OpenAiChatModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.service.AiServices&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.service.UserMessage&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AiServicesWordAnalysis&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;WordAnalysis&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;OFFENSIVE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;BAD&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;NEUTRAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;GOOD&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;WordModerator&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Analyze the profanity of {{it}}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;WordAnalysis&lt;/span&gt; &lt;span class="nf"&gt;analyzeWords&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Does {{it}} have a profanity?"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isProfane&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Provide alternate better words for the profane words in {{it}}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;alternateWords&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;ChatLanguageModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAiChatModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withApiKey&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"demo"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;WordModerator&lt;/span&gt; &lt;span class="n"&gt;moderator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AiServices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WordModerator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;WordAnalysis&lt;/span&gt; &lt;span class="n"&gt;analysis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;moderator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;analyzeWords&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"He is shit"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Analysis: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isProfane&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moderator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isProfane&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"He is a dumbo"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Is Profane: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;isProfane&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;replacements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moderator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;alternateWords&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"He is not intelligent but a shit and dumbo"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;replacements&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we define our interface &lt;code&gt;WordModerator&lt;/code&gt; that defines three methods and the enum &lt;code&gt;WordAnalysis&lt;/code&gt; to be supplied to the &lt;code&gt;AiServices&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;WordAnalysis&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;OFFENSIVE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;BAD&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;NEUTRAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;GOOD&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;WordModerator&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Analyze the profanity of {{it}}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;WordAnalysis&lt;/span&gt; &lt;span class="nf"&gt;analyzeWords&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Does {{it}} have a profanity?"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isProfane&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Provide alternate better words for the profane words in {{it}}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;alternateWords&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;analyzeWords&lt;/code&gt; determines if the degree of profanity in the given text as defined in the enum &lt;code&gt;WordAnalysis&lt;/code&gt; - &lt;code&gt;OFFENSIVE&lt;/code&gt;, &lt;code&gt;BAD&lt;/code&gt;, &lt;code&gt;NEUTRAL&lt;/code&gt;, &lt;code&gt;GOOD&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isProfane&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; indicating the presence of profanity in the given text.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;alternateWords&lt;/code&gt; finds out the list of words that are profane and the LLM provides alternate words to be replaced for those words&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As mentioned above, &lt;code&gt;AiServices&lt;/code&gt; handles the conversion of input/output between the application and the LLM in a transparent manner.&lt;/p&gt;

&lt;p&gt;The following is what the LLM returns when running the code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Analysis: OFFENSIVE
Is Profane: true
{shit=fool, dumbo=dimwit}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the next example, we will see how &lt;code&gt;AiServices&lt;/code&gt; deals with POJOs. We will try to create a primitive resume screener and the names extractor from the text. It is quite similar to the previous example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j:0.29.1&lt;/span&gt;
&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j-ollama:0.29.1&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.Duration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.chat.ChatLanguageModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.ollama.OllamaChatModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.service.AiServices&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.service.UserMessage&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AiServicesCandidateInfo&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"mistral"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://localhost:11434"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Candidate&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;experience&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;profession&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="nd"&gt;@Override&lt;/span&gt;
        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Candidate: [firstName="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", lastName="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", email="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", experience="&lt;/span&gt;
                    &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;experience&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", profession="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;profession&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", phone="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"]"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;CandidateInfoCollector&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Extract information about a person from {{it}}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;Candidate&lt;/span&gt; &lt;span class="nf"&gt;extractCandidateInfo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Extract all person names from {{it}}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;extractPersonNames&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;ChatLanguageModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OllamaChatModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;BASE_URL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MODEL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;CandidateInfoCollector&lt;/span&gt; &lt;span class="n"&gt;candidateInfoCollector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AiServices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CandidateInfoCollector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""
                I am Arjun Kumar, I have been working at a Software Developer for 5 years.
                Email: arjun@myemail.com
                Phone: +919876543210
                """&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;Candidate&lt;/span&gt; &lt;span class="n"&gt;candidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candidateInfoCollector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;extractCandidateInfo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""
                There was an interview being conducted in a software company. 
                Arjun and Ananya planned to attend the interview.
                Next morning they went to the venue.
                There they met their friends Akash, Mithun, Sita, Kausalya and Kumar who were also attending.
                The interviewers were Bob and Steve!
                """&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Person person = personExtractor.extractPersonFrom(text);&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candidateInfoCollector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;extractPersonNames&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we define our POJO - &lt;code&gt;Candidate&lt;/code&gt; and also override the &lt;code&gt;toString&lt;/code&gt; method&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Candidate&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;experience&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;profession&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interface &lt;code&gt;CandidateInfoCollector&lt;/code&gt; defines the two methods annotated with the &lt;code&gt;UserMessage&lt;/code&gt; instruction&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;CandidateInfoCollector&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Extract information about a person from {{it}}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Candidate&lt;/span&gt; &lt;span class="nf"&gt;extractCandidateInfo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Extract all person names from {{it}}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;extractPersonNames&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the code extracts the POJO object and the list of names&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Candidate: [firstName=Arjun, lastName=Kumar, email=arjun@myemail.com, experience=5 years, profession=Software Developer, phone=+919876543210]

[ Arjun, Ananya, Akash, Mithun, Sita, Kausalya, Kumar, Bob, Steve]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see from the examples above, &lt;code&gt;AiServices&lt;/code&gt; enables the developer to focus on the business logic by taking away the complexities of interacting with the LLM and handling the different data types transparently.&lt;/p&gt;

&lt;p&gt;There are more to be explored in LangChain4j such as Tools (Function Calling), Retrieval Augmented Generation (RAG), etc. We will explore those in the upcoming articles.&lt;/p&gt;

&lt;p&gt;The code examples are available on &lt;a href="https://github.com/rprabhu/ai-ml-langchain4j"&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>langchain4j</category>
      <category>java</category>
      <category>ollama</category>
    </item>
    <item>
      <title>AI/ML - Langchain4j - Chat Memory</title>
      <dc:creator>Prabhu R</dc:creator>
      <pubDate>Thu, 28 Mar 2024 11:04:04 +0000</pubDate>
      <link>https://dev.to/rprabhu/aiml-langchain4j-chat-memory-3b31</link>
      <guid>https://dev.to/rprabhu/aiml-langchain4j-chat-memory-3b31</guid>
      <description>&lt;p&gt;In the &lt;a href="https://blog.teamnexus.in/blog/2024/03/20/beginning-the-ai-ml-journey-with-ollama-langchain4j-jbang/"&gt;preceding article&lt;/a&gt;, we were introduced to AI/ML concepts and explored the process of running a local Large Language Model (LLM) - &lt;a href="https://ollama.com"&gt;Ollama&lt;/a&gt;.  We further delved into interacting with it via Java using &lt;a href="https://www.jbang.dev"&gt;JBang&lt;/a&gt; and &lt;a href="https://docs.langchain4j.dev/"&gt;Langchain4j&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, let's explore into what &lt;em&gt;"chat memory"&lt;/em&gt; is and how langchain4j helps in the cumbersome task of maintaining the chat memory.&lt;/p&gt;

&lt;p&gt;To begin with, let's discuss the necessity of chat memory. Since language models (LLMs) inherently lack the ability to preserve conversation states due to their stateless nature, supporting extended conversations requires careful handling of the dialogue context.&lt;/p&gt;

&lt;p&gt;If we run the &lt;code&gt;OllamaMistralExample&lt;/code&gt; from the &lt;a href="https://blog.teamnexus.in/blog/2024/03/20/beginning-the-ai-ml-journey-with-ollama-langchain4j-jbang/"&gt;previous article&lt;/a&gt;, the following are the responses from the model&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please enter your question - 'exit' to quit: My name is Kevin, the minion. I work for Gru!

 Hello Kevin the Minion! It's great to meet you, the dedicated and hardworking minion from Gru's team. I'm here to help answer any questions or provide information you may need. What can I assist you with today?

Please enter your question - 'exit' to quit: Who is my boss? 

 I cannot determine who your boss is as I don't have the ability to access or interpret real-world information. Your boss would be the person who has authority over you in your workplace, such as a manager or supervisor. If you are unsure, it may be best to ask someone in a position of seniority within your organization or consult your employment contract or HR department for clarification.

Please enter your question - 'exit' to quit: What is my name?  

 I am an artificial intelligence and do not have a name or personal identity. I exist to provide information and answer questions to the best of my ability. How may I assist you today?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the responses above, we can clearly see that the model does not remember the context of the conversation during the interaction with the LLM as they don't remember the state. Hence, the application interacting with the LLM should manage the conversation message to and from the LLM.&lt;/p&gt;

&lt;p&gt;For sending multiple messages, langchain4j's &lt;code&gt;ChatLanguageModel&lt;/code&gt; interface provides the following methods&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ChatMessage&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ChatMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ChatMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ToolSpecification&lt;/span&gt; &lt;span class="n"&gt;toolSpecification&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ChatMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ToolSpecification&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;toolSpecifications&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's see a code example that uses the second method in the &lt;code&gt;ChatLanguageModel&lt;/code&gt; interface, that is &lt;code&gt;Response&amp;lt;AiMessage&amp;gt; generate(List&amp;lt;ChatMessage&amp;gt; messages);&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;//JAVA 21&lt;/span&gt;
&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j:0.28.0&lt;/span&gt;
&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j-ollama:0.28.0&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.Console&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.Duration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.ArrayList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.data.message.AiMessage&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.data.message.ChatMessage&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.data.message.UserMessage&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.StreamingResponseHandler&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.chat.StreamingChatLanguageModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.ollama.OllamaStreamingChatModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.output.Response&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OllamaMistralBasicMemory&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"mistral"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://localhost:11434"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;beginChatWithBasicMemory&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;beginChatWithBasicMemory&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;Console&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;console&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ChatMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;StreamingChatLanguageModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OllamaStreamingChatModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;BASE_URL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MODEL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"\n\nPlease enter your question - 'exit' to quit: "&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="s"&gt;"exit"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
            &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;futureResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StreamingResponseHandler&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                &lt;span class="nd"&gt;@Override&lt;/span&gt;
                &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onNext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;

                &lt;span class="nd"&gt;@Override&lt;/span&gt;
                &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onComplete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
                    &lt;span class="n"&gt;futureResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;

                &lt;span class="nd"&gt;@Override&lt;/span&gt;
                &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;futureResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;completeExceptionally&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;});&lt;/span&gt;

            &lt;span class="n"&gt;futureResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n\nPlease enter your question - 'exit' to quit: "&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;OllamaMistralBasicMemory&lt;/code&gt; class is a modified version of &lt;code&gt;OllamaMistralExample&lt;/code&gt; class from the &lt;a href="https://blog.teamnexus.in/blog/2024/03/20/beginning-the-ai-ml-journey-with-ollama-langchain4j-jbang/"&gt;previous article&lt;/a&gt;. We use the &lt;code&gt;StreamingChatLanguageModel&lt;/code&gt;  which let's us get the response immediately for each token generated rather than having to wait for the full response.&lt;/p&gt;

&lt;p&gt;Here we use an ArrayList to store the &lt;code&gt;UserMessage&lt;/code&gt; and the &lt;code&gt;AiMessage&lt;/code&gt; that gets sent to the LLM whenever we want the LLM to generate the response.&lt;/p&gt;

&lt;p&gt;After each input received from the user, &lt;code&gt;messages.add(UserMessage.from(question));&lt;/code&gt; adds the user input to the list and when the response is completely received it triggers the event &lt;code&gt;onComplete(Response&amp;lt;AiMessage&amp;gt; response)&lt;/code&gt; which in turn adds the message to the list of messages by &lt;code&gt;messages.add(response.content());&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Now, try executing the &lt;code&gt;OllamaMistralBasicMemory&lt;/code&gt;, and now the responses seem to align with what we expect and it seems to know the context. The following is the output for the same conversation as above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please enter your question - 'exit' to quit: My name is Kevin, the minion. I work for Gru!

 Hello Kevin the Minion! It's great to meet you, the dedicated and hardworking minion from Gru's team. I'm here to help answer any questions or provide information you may need. What can I assist you with today?

Please enter your question - 'exit' to quit: What is my name?                 

 I apologize for the confusion earlier, Kevin. You have introduced yourself as Kevin the Minion. So, your name is indeed Kevin! Is there something specific you would like to know or discuss related to Gru's lab or minion activities?

Please enter your question - 'exit' to quit: Who is my boss?

 Your boss is Gru! He is the mastermind and leader of the evil organization that you and your fellow Minions work for. Gru is known for his cunning plans and schemes, and he relies on your help to carry them out. If you have any questions or need assistance with tasks related to Gru's plans, feel free to ask!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, the LLM remembers the context and starts providing appropriate responses to the questions. However, there are a few problems with this implementation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, LLMs possess a finite context window that accommodates a certain number of tokens at any given moment. Conversations have the potential to surpass this limit&lt;/li&gt;
&lt;li&gt;Second, each token comes with a cost, which increases progressively as more tokens are requested from the LLM&lt;/li&gt;
&lt;li&gt;Third, the resource usage increases considerably on both the LLM and the application over time as the list builds up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Managing &lt;code&gt;ChatMessage&lt;/code&gt;s manually is an arduous task. To simplify this process, LangChain4j provides the &lt;code&gt;ChatMemory&lt;/code&gt; interface for managing &lt;code&gt;ChatMessage&lt;/code&gt;s that is backed by a &lt;code&gt;List&lt;/code&gt;, offering additional features such as persistence (as provided by &lt;code&gt;ChatMemoryStore&lt;/code&gt;) and the essential &lt;em&gt;"eviction policy"&lt;/em&gt;. This eviction policy to address the issues described above.&lt;/p&gt;

&lt;p&gt;LangChain4j currently implements two algorithms for eviction policy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;MessageWindowChatMemory&lt;/code&gt; provides a sliding window functionality, retaining the &lt;code&gt;N&lt;/code&gt; most recent messages and evicting the older ones when it goes beyond the specified capacity &lt;code&gt;N&lt;/code&gt;. However, the &lt;code&gt;SystemMessage&lt;/code&gt; type of &lt;code&gt;ChatMessage&lt;/code&gt; is retained and not evicted. The other types of messages &lt;code&gt;UserMessage&lt;/code&gt;, &lt;code&gt;AiMessage&lt;/code&gt; and &lt;code&gt;ToolExecutionResultMessage&lt;/code&gt; will be evicted&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TokenWindowChatMemory&lt;/code&gt; also provides a sliding window functionality but retains the &lt;code&gt;N&lt;/code&gt; most recent &lt;strong&gt;tokens&lt;/strong&gt; instead of messages. A &lt;code&gt;Tokenizer&lt;/code&gt; needs to be specified to count the tokens in each &lt;code&gt;ChatMessage&lt;/code&gt;.  If there isn't enough space for a new message, the oldest one (or multiple) is evicted. Messages are indivisible. If a message doesn't fit, it is evicted completely. Like the &lt;code&gt;MessageWindowChatMemory&lt;/code&gt;, &lt;code&gt;SystemMessage&lt;/code&gt; is not evicted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, let's implement the &lt;code&gt;OllamaMistralBasicMemory&lt;/code&gt; using &lt;code&gt;ChatMemory&lt;/code&gt; with the &lt;code&gt;MessageWindowChatMemory&lt;/code&gt; eviction policy&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;//JAVA 21&lt;/span&gt;
&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j:0.28.0&lt;/span&gt;
&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j-ollama:0.28.0&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.Console&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.Duration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.data.message.AiMessage&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.data.message.UserMessage&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.memory.ChatMemory&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.memory.chat.MessageWindowChatMemory&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.StreamingResponseHandler&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.chat.StreamingChatLanguageModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.ollama.OllamaStreamingChatModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.output.Response&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OllamaMistralChatMemory&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"mistral"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://localhost:11434"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;beginChatWithChatMemory&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;beginChatWithChatMemory&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;Console&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;console&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;ChatMemory&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageWindowChatMemory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withMaxMessages&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;StreamingChatLanguageModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OllamaStreamingChatModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;BASE_URL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MODEL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"\n\nPlease enter your question - 'exit' to quit: "&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="s"&gt;"exit"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

            &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
            &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;futureResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StreamingResponseHandler&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                &lt;span class="nd"&gt;@Override&lt;/span&gt;
                &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onNext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;

                &lt;span class="nd"&gt;@Override&lt;/span&gt;
                &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onComplete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
                    &lt;span class="n"&gt;futureResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;

                &lt;span class="nd"&gt;@Override&lt;/span&gt;
                &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;futureResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;completeExceptionally&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;});&lt;/span&gt;

            &lt;span class="n"&gt;futureResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n\nPlease enter your question - 'exit' to quit: "&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have set the max messages to &lt;code&gt;3&lt;/code&gt; for the sake of testing it quickly. A higher value can be set if needed. Therefore, the max number of &lt;code&gt;ChatMessage&lt;/code&gt;s that are retained is &lt;code&gt;3&lt;/code&gt; including question (&lt;code&gt;UserMessage&lt;/code&gt;) and response (&lt;code&gt;AiMessage&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;If we run the program and specify our name first, then ask a few more questions so that the context of name gets evicted after 3 messages. Now if we ask the LLM for the name, the LLM does not have the content as the &lt;code&gt;MessageWindowChatMemory&lt;/code&gt; has evicted those messages. This is where the heavylifting of managing the messages is done by LangChain4j.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ChatMemory&lt;/code&gt; is a low-level component to manage the messages. However, there are high-level components &lt;code&gt;AiServices&lt;/code&gt; and &lt;code&gt;ConversationalChain&lt;/code&gt; that are available in LangChain4j. We will explore those in the upcoming articles.&lt;/p&gt;

&lt;p&gt;The code examples can be found &lt;a href="https://github.com/rprabhu/ai-ml-langchain4j"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>langchain4j</category>
      <category>jbang</category>
      <category>ollama</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Beginning the AI/ML Journey with Ollama, Langchain4J &amp; JBang</title>
      <dc:creator>Prabhu R</dc:creator>
      <pubDate>Wed, 20 Mar 2024 10:19:40 +0000</pubDate>
      <link>https://dev.to/rprabhu/beginning-the-aiml-journey-with-ollama-langchain4j-jbang-1opn</link>
      <guid>https://dev.to/rprabhu/beginning-the-aiml-journey-with-ollama-langchain4j-jbang-1opn</guid>
      <description>&lt;p&gt;The realm of AI/ML, especially Generative AI, has garnered significant attention worldwide following the emergence of &lt;a href="https://chat.openai.com/"&gt;ChatGPT&lt;/a&gt;. Consequently, there has been a surge of interest in developing various models and tools within this domain.&lt;/p&gt;

&lt;p&gt;In this article, we will take a look at how to interact with AI models using Java. But before that, we will take a look at what an "AI Model" is, the terms and concepts related to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI/ML Primer
&lt;/h2&gt;

&lt;p&gt;Artificial intelligence (AI) models are computational algorithms crafted to process and produce information, often emulating human cognitive abilities. By assimilating patterns and insights from extensive datasets, these models have the capacity to generate predictions, text, images, or other forms of output, thereby augmenting a multitude of applications spanning diverse industries.&lt;/p&gt;

&lt;p&gt;Numerous AI models exist, each tailored to serve specific purposes. While ChatGPT has garnered attention for its text input and output capabilities, other models and companies provide a range of inputs and outputs to cater to diverse needs that includes Images, Audio, Video etc.&lt;/p&gt;

&lt;p&gt;What distinguishes models such as GPT (Generative Pre-trained Transformer) is this pre-training functionality transforms AI into a versatile developer tool, eliminating the need for a deep understanding of machine learning or model training. &lt;/p&gt;

&lt;h3&gt;
  
  
  LLM - Large Language Models
&lt;/h3&gt;

&lt;p&gt;LLM (Large Language Model) refers to a type of AI model designed to understand and generate human-like text at a high level of proficiency. LLMs are trained on vast amounts of text data and are capable of performing a wide range of natural language processing tasks, including text generation, translation, summarization, question answering, and more. Examples of LLMs include GPT (Generative Pre-trained Transformer) models such as GPT-3, BERT (Bidirectional Encoder Representations from Transformers), and others. These models have demonstrated impressive capabilities in understanding and generating text, leading to their widespread use in various applications, including chatbots, virtual assistants, content creation tools, and more.&lt;/p&gt;

&lt;p&gt;Integrating LLM into applications requires access to LLM Provides like OpenAI, Google Vertex AI, Azure OpenAI etc., or software like Ollama, LM Studio, LocalAI etc that allow LLMs to be run locally. We will see about running LLMs locally later in this article.&lt;/p&gt;

&lt;p&gt;Let's see some more terms and concepts before we get into the code integrating with LLMs&lt;/p&gt;

&lt;h3&gt;
  
  
  Tokens
&lt;/h3&gt;

&lt;p&gt;In the context of Large Language Models (LLMs), tokens refer to the basic units of text that the model processes. These tokens can represent individual words, subwords, or even characters, depending on how the model is trained and configured.&lt;/p&gt;

&lt;p&gt;When a piece of text is input into an LLM, it is typically tokenized into smaller units before being processed by the model. Each token corresponds to a specific unit of text, and the model generates output based on the patterns and relationships it learns from the input tokens.&lt;/p&gt;

&lt;p&gt;Tokenization is a crucial step in the operation of LLMs, as it allows the model to break down complex text data into manageable units for processing. By tokenizing text, LLMs can analyze and generate responses with a granular level of detail, enabling them to understand and generate human-like text.&lt;/p&gt;

&lt;p&gt;Tokenization can vary based on the specific tokenization scheme used and the vocabulary size of the model&lt;/p&gt;

&lt;p&gt;In some tokenization schemes, a single word may be split into multiple tokens, especially if it contains complex morphology or is not present in the model's vocabulary. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Word:&lt;/strong&gt; "university"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tokens:&lt;/strong&gt; ["uni", "vers", "ity"]&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; In this example, the word "university" is split into three tokens: "uni", "vers", and "ity". This decomposition allows the model to capture the morphological structure of the word.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conversely, multiple consecutive words may be combined into a single token, particularly in subword tokenization schemes like Byte Pair Encoding (BPE) or WordPiece. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Phrase:&lt;/strong&gt; "natural language processing"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token:&lt;/strong&gt; "natural_language_processing"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; In this example, the phrase "natural language processing" is combined into a single token "natural_language_processing". This allows the model to treat the entire phrase as a single unit during processing, which can be beneficial for capturing multi-word expressions or domain-specific terminology.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The examples provided above are for the purposes of understanding and need not represent how it is actually processed by the LLM&lt;/p&gt;

&lt;h3&gt;
  
  
  Prompts and Prompt Templates
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Prompts
&lt;/h4&gt;

&lt;p&gt;Prompts lay the groundwork for language-based inputs, directing an AI model towards generating particular outputs. While those acquainted with ChatGPT might view prompts as mere textual inputs submitted through a dialog box to the API, their significance extends beyond this. In numerous AI models, the prompt text transcends a mere string, encompassing broader contextual elements. As we saw in the previous section on tokens, how tokens are processed varies differently based on the context and the tokenization schemes.&lt;/p&gt;

&lt;p&gt;Developing compelling prompts is a blend of artistic creativity and scientific precision. The significance of this interaction method has led to the emergence of &lt;em&gt;"Prompt Engineering"&lt;/em&gt; as a distinct discipline. A plethora of techniques aimed at enhancing prompt effectiveness are continually evolving. Dedication to refining a prompt can markedly enhance the resultant output.&lt;/p&gt;

&lt;h4&gt;
  
  
  Prompt Templates
&lt;/h4&gt;

&lt;p&gt;Prompt templates serve as structured guides for crafting effective prompts, helping users communicate their intentions clearly and succinctly to AI models.&lt;/p&gt;

&lt;p&gt;Prompt templates can vary depending on the specific use case or application domain. They may include placeholders for variables or user inputs, guiding users to provide contextually relevant information. By following a prompt template, users can ensure consistency and clarity in their prompts, which in turn improves the performance and relevance of the AI model's responses.&lt;/p&gt;

&lt;p&gt;For example, a prompt template for a chatbot might include placeholders for the user's inquiry, desired action, and any relevant context or constraints. By filling in these placeholders with specific details, users can create well-formed prompts that elicit accurate and useful responses from the chatbot. Following is a sample chatbot prompt template&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Planning to book a [service]? 
Let me know your preferred date and time and 
I'll assist you with the booking process.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enhancing/Updating the Data to the AI Model
&lt;/h3&gt;

&lt;p&gt;GPT 3.5/4.0 dataset extends only until September 2021 which becomes an apparent limitation for getting updated data. Consequently, the model says that it does not know the answer to questions that require knowledge beyond that date. The dataset can be from a few hundred gigabytes to a few petabytes. &lt;/p&gt;

&lt;p&gt;In order to incorporate additional data to the model the following techniques are used&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fine Tuning:&lt;/strong&gt; a conventional method in machine learning, entails adjusting the model's parameters and altering its internal weighting. This extremely resource-intensive process is a challenge when training large models like GPT and certain models may not provide this capability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Retrieval Augmented Generation (RAG):&lt;/strong&gt; RAG, also referred to as &lt;em&gt;"Prompt Stuffing"&lt;/em&gt;, offers a pragmatic approach. In this method, the system extracts unstructured data from documents, processes it, and stores it in a vector database such as &lt;a href="https://www.trychroma.com/"&gt;Chroma&lt;/a&gt;, &lt;a href="https://www.pinecone.io/"&gt;Pinecone&lt;/a&gt;, &lt;a href="https://milvus.io/"&gt;Milvus&lt;/a&gt;, &lt;a href="https://qdrant.tech/"&gt;Qdrant&lt;/a&gt;, and others. During retrieval, when an AI model is tasked with answering a user's query, the question along with all "similar" document fragments retrieved from the vector database are incorporated into the prompt forwarded to the AI model.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Function Calling:&lt;/strong&gt; This mechanism facilitates the registration of custom user functions, linking large language models with external system APIs. These systems enable LLMs to access real-time data and execute data processing tasks on their behalf.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Integrating LLMs into applications
&lt;/h2&gt;

&lt;p&gt;Now let's dive into the coding aspect of integrating LLMs in the applications. The following are the prerequisites&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ollama:&lt;/strong&gt; &lt;a href="https://ollama.com"&gt;Ollama&lt;/a&gt; is a lightweight, extensible framework for building and running language models on your local machine. It provides a simple API for creating, running, and managing models, as well as a library of pre-built models that can be easily used in a variety of applications. Download and install the appropriate binary for your OS. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Langchain4j:&lt;/strong&gt; &lt;a href="https://docs.langchain4j.dev/"&gt;LangChain4j&lt;/a&gt; is a Java library designed to simplify integrating AI and large language models (LLMs) into Java applications. It offers a unified API to avoid the need for learning and implementing specific APIs for each of them. To experiment with a different LLM or embedding store, you can easily switch between them without the need to rewrite your code. LangChain4j currently supports over 10 popular LLM providers and more than 15 embedding stores.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JBang:&lt;/strong&gt; &lt;a href="https://www.jbang.dev"&gt;JBang&lt;/a&gt; is a neat little tool that enables running Java code as script. It directly runs the java source file and saves the effort of setting up or configuring the project for Maven, Gradle or any other build system. It also manages the dependencies of external libraries in the comment of the source itself as we'll see in the following code. You can also read about JBang in our &lt;a href="https://blog.teamnexus.in/blog/2020/07/26/jbang-the-power-of-shell-scripting-for-java/"&gt;previous article&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;First, download the &lt;a href="https://ollama.com"&gt;Ollama&lt;/a&gt; binary and install it. Alternatively, one can install &lt;a href="https://lmstudio.ai/"&gt;LM Studio&lt;/a&gt; as well, that allows running of the LLM models locally. However, in this article, we will use &lt;a href="https://ollama.com"&gt;Ollama&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next download and run the Ollama LLM model. Executing the following command in the shell downloads and runs the LLM&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama run mistral
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run any other model like llama2, phi etc as well. However, note that &lt;code&gt;Ollama&lt;/code&gt; will download the required model which will be a few gigabytes in size.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Download and install &lt;a href="https://www.jbang.dev"&gt;JBang&lt;/a&gt;. When executing the code, JBang expects the Java binary to be in the PATH, if not &lt;a href="https://www.jbang.dev"&gt;JBang&lt;/a&gt; will download the necessary JDK as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type the following code in your editor and save it as &lt;code&gt;OllamaMistralExample.java&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;//JAVA 21&lt;/span&gt;
&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j:0.28.0&lt;/span&gt;
&lt;span class="c1"&gt;//DEPS dev.langchain4j:langchain4j-ollama:0.28.0&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.Console&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.Duration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.data.message.AiMessage&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.StreamingResponseHandler&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.chat.ChatLanguageModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.chat.StreamingChatLanguageModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.ollama.OllamaChatModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.ollama.OllamaStreamingChatModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;dev.langchain4j.model.output.Response&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OllamaMistralExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"mistral"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://localhost:11434"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Console&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;console&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"Welcome, Butler at your service!!\n\nPlease choose your model - Type '1' for the Basic Model and '2' for Streaming Model:"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n\nPlease enter your question - 'exit' to quit: "&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="s"&gt;"exit"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;basicModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;streamingModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n\nPlease enter your question - 'exit' to quit: "&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;basicModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;ChatLanguageModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OllamaChatModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;BASE_URL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MODEL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n\nPlease wait...\n\n"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;streamingModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;StreamingChatLanguageModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OllamaStreamingChatModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;BASE_URL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MODEL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;futureResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StreamingResponseHandler&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onNext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;

            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onComplete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AiMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;futureResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;

            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;futureResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;completeExceptionally&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;});&lt;/span&gt;

        &lt;span class="n"&gt;futureResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Now type the following command to run the program, we will see the explanation to this shortly.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jbang OllamaMistralExample.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JBang automatically downloads the dependencies and runs this Java file.&lt;/p&gt;

&lt;p&gt;Now let's get into the code&lt;/p&gt;

&lt;p&gt;The comment line at the top of the file are processed by JBang. &lt;code&gt;//JAVA&lt;/code&gt; comment line indicates the target JDK version and the ones that start with &lt;code&gt;// DEPS&lt;/code&gt; define the library dependencies. Here we define the Langchain4j libraries (core + ollama) that JBang downloads and processes. For further details about the JBang comment lines, please visit the &lt;a href="https://www.jbang.dev"&gt;JBang website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The jbang OllamaMistralExample class defines two methods apart from the &lt;code&gt;main&lt;/code&gt; method - &lt;code&gt;basicModel&lt;/code&gt; and &lt;code&gt;streamingModel&lt;/code&gt;. The quick difference them is that the &lt;code&gt;basicModel&lt;/code&gt; waits for the LLM to generate the full response and respond back. The user will have to wait until the LLM completes the generation. LLMs generate one token at a time, so the LLM Providers offer a way to stream the tokens as soon as they are generated which significantly improves the user experience as the user can start reading the response almost immediately than waiting for the entire response. Therefore, the &lt;code&gt;streamingModel&lt;/code&gt; method harnesses this streaming capability and starts to output the response as soon it receives from the LLM Provider.&lt;/p&gt;

&lt;p&gt;Langchain4j provides APIs for both the standard response and streaming response. The &lt;code&gt;ChatLanguageModel&lt;/code&gt; interface is for getting the standard response and the &lt;code&gt;StreamingChatLanguageModel&lt;/code&gt; interface is for the streaming response. Both the interfaces provide similar methods, however the &lt;code&gt;StreamingChatLanguageModel&lt;/code&gt; requires the &lt;code&gt;StreamingResponseHandler&lt;/code&gt; interface implementation to be passed as an argument. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;StreamingResponseHandler&lt;/code&gt; interface specifies the following methods&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;StreamingResponseHandler&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onNext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onComplete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;onNext&lt;/code&gt; gets called when the LLM generates a token and responds back.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onComplete&lt;/code&gt; is a default method that does nothing, however can be overriden to deal with the complete response that gets delivered once the LLM has completed generating the response.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onError&lt;/code&gt; is invoked when there is an error generating the response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;basicModel&lt;/code&gt; method uses the &lt;code&gt;OllamaChatModel.builder()&lt;/code&gt; to build the class implementing the &lt;code&gt;ChatLanguageModel&lt;/code&gt; interface and the &lt;code&gt;streamingModel&lt;/code&gt; method uses the &lt;code&gt;OllamaStreamingChatModel.builder()&lt;/code&gt; to build the class implementing the &lt;code&gt;StreamingChatLanguageModel&lt;/code&gt; interface.&lt;/p&gt;

&lt;p&gt;For both the interface types - standard and streaming the following fields need to be passed to the builders of each type&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Base URL: &lt;code&gt;http://localhost:11434&lt;/code&gt; The URL and port where Ollama exposes the LLM service&lt;/li&gt;
&lt;li&gt;Model Name: &lt;code&gt;mistral&lt;/code&gt; in this example.&lt;/li&gt;
&lt;li&gt;Timeout: Timeout is optional, however it is safe to set it in a local environment because LLMs could be slow to generate response due to resource constraints like No GPU, less memory etc. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both the &lt;code&gt;ChatLanguageModel&lt;/code&gt; and &lt;code&gt;StreamingChatLanguageModel&lt;/code&gt; interfaces provide the generate method which is similar however as mentioned above, the &lt;code&gt;StreamingChatLanguageModel&lt;/code&gt;'s &lt;code&gt;generate&lt;/code&gt; method expects an additional argument which is the implementation of the &lt;code&gt;StreamingResponseHandler&lt;/code&gt; interface.&lt;/p&gt;

&lt;p&gt;Try running the code above and enter into the world of AI/ML using LLMs. What we have seen above is just the beginning. There's a lot more to explore in this space, especially what Langchain4j offers - &lt;code&gt;AiServices&lt;/code&gt;, &lt;code&gt;Structured Data Extraction&lt;/code&gt;, &lt;code&gt;Chains&lt;/code&gt;, &lt;code&gt;Embedding&lt;/code&gt;, &lt;code&gt;RAG&lt;/code&gt;, &lt;code&gt;Function Calling&lt;/code&gt; and more. &lt;/p&gt;

&lt;p&gt;Apart from Langchain4j, &lt;a href="https://docs.spring.io/spring-ai/reference/index.html"&gt;Spring AI&lt;/a&gt; also has support for AI/ML the same way Langchain4j does. We'll explore those in the upcoming articles.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>langchain4j</category>
      <category>ollama</category>
      <category>jbang</category>
    </item>
    <item>
      <title>Marp: A Markdown Presentation App That Simplifies Your Tech Talks</title>
      <dc:creator>Prabhu R</dc:creator>
      <pubDate>Tue, 12 Mar 2024 16:02:00 +0000</pubDate>
      <link>https://dev.to/rprabhu/marp-a-markdown-presentation-app-that-simplifies-your-tech-talks-37m4</link>
      <guid>https://dev.to/rprabhu/marp-a-markdown-presentation-app-that-simplifies-your-tech-talks-37m4</guid>
      <description>&lt;p&gt;In today's fast-paced tech world, giving effective presentations is crucial for conveying complex ideas and engaging audiences. While Markdown has emerged as a popular lightweight markup language for creating rich text documents, its use in creating dynamic, interactive, and visually appealing presentations can be challenging. This is where Marp comes into the picture - an open-source Markdown presentation app that simplifies the process of creating engaging tech talks. In our &lt;a href="https://blog.teamnexus.in/blog/2022/06/07/stunning-presentations-with-asciidoctor-and-revealjs/"&gt;earlier post&lt;/a&gt;, we saw about how Asciidoctor can be used to create stunning presentations, and in this article it is &lt;a href="https://daringfireball.net/projects/markdown/"&gt;markdown&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Marp?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://marp.app/"&gt;Marp (Markdown Presentation Engine)&lt;/a&gt; is a lightweight and flexible tool for creating interactive and visually appealing presentations using simple Markdown syntax. It was created based on the idea of combining the benefits of Markdown and Reveal.js, a popular HTML presentation framework. Marp supports the creation of presentations that can be rendered as static HTML, PDF, or PowerPoint&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Simple Markdown syntax:&lt;/strong&gt; Marp uses a straightforward Markdown format for creating slides, making it easy for developers and writers who are already familiar with Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive presentations:&lt;/strong&gt; Marp supports the use of JavaScript and HTML to create interactive elements, such as quizzes, forms, and animations, to enhance user engagement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live preview:&lt;/strong&gt; Marp provides a live preview mode while editing, allowing you to see the changes in real-time and fine-tune your slides without leaving the editor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Directives and extended syntax:&lt;/strong&gt; Marp supports a variety of directives and extended syntax (image syntax, math typesetting, auto-scaling, etc...)  to create beautiful slides, as sometimes, simple text content isn't enough to emphasize or represent the content - mathematical equations for example.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export to various formats:&lt;/strong&gt; Marp supports exporting presentations in multiple formats such as HTML, PDF, and SVG, allowing you to share your content with a broader audience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable themes:&lt;/strong&gt; Marp offers several built-in themes to choose from or the option to create custom themes, enabling you to design presentations that align with your brand and style.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Official Toolset:&lt;/strong&gt; Marp provides an official toolset that has the &lt;a href="https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode"&gt;Visual Studio Code extension&lt;/a&gt; and &lt;a href="https://github.com/marp-team/marp-cli"&gt;Marp CLI&lt;/a&gt; for command line usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pluggable Architecture:&lt;/strong&gt; Marp ecosystem is based on the Marpit framework for creating HTML slides deck and has a pluggable architecture where the features can be extended by developers via plugins&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;The recommended and the best option is to use the &lt;a href="https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode"&gt;Visual Studio Code extension&lt;/a&gt; that is provided. The &lt;a href="https://github.com/marp-team/marp-cli"&gt;Marp CLI&lt;/a&gt;, the command line version, can also be used. However, one has to compile it to the required output everytime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases
&lt;/h2&gt;

&lt;p&gt;Marp is an ideal solution for developers, designers, educators, and anyone who needs to create engaging technical or informational presentations. Some common use cases include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Software demos:&lt;/strong&gt; Marp can be used to create presentations that showcase the features of a software product or application, with interactive elements that allow users to interact and explore the functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Educational materials:&lt;/strong&gt; Marp is an excellent tool for creating engaging educational materials such as tutorials, workshop guides, or study resources, with the ability to add code snippets, diagrams, and other multimedia content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technical talks:&lt;/strong&gt; Marp simplifies the process of creating technical talks and workshops by offering a lightweight and flexible presentation engine that can handle complex content, interactive elements, and customizable styles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data visualizations:&lt;/strong&gt; Marp supports integrations with libraries like D3.js and Plotly, making it an ideal choice for data scientists and researchers who need to present complex data visualizations in an engaging and accessible format.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Sample
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;
---&lt;/span&gt;
theme: gaia
_class: lead
paginate: true
backgroundColor: #fff
&lt;span class="gh"&gt;backgroundImage: url('https://marp.app/assets/hero-background.svg')
---
&lt;/span&gt;
&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;bg left:40% 80%&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://marp.app/assets/marp.svg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="gh"&gt;# **Marp**&lt;/span&gt;

Markdown Presentation Ecosystem

https://marp.app/
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gh"&gt;# How to write slides&lt;/span&gt;

Split pages by horizontal ruler (&lt;span class="sb"&gt;`---`&lt;/span&gt;). It's very simple! :satisfied:
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gh"&gt;# Slide 1&lt;/span&gt;

foobar
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gh"&gt;# Slide 2&lt;/span&gt;

foobar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Marp offers a simple yet powerful solution for creating interactive and visually appealing technical presentations using Markdown syntax. With its live preview mode, customizable themes, and support for various export formats, it provides developers, educators, and presenters with an essential tool for engaging audiences and conveying complex ideas effectively. So, next time you need to create a presentation, consider giving Marp a try!&lt;/p&gt;

</description>
      <category>presentation</category>
      <category>markdown</category>
      <category>opensource</category>
    </item>
    <item>
      <title>jsoup: A Powerful Java Library for Working With HTML and XML Documents</title>
      <dc:creator>Prabhu R</dc:creator>
      <pubDate>Mon, 11 Mar 2024 09:17:43 +0000</pubDate>
      <link>https://dev.to/rprabhu/jsoup-a-powerful-java-library-for-working-with-html-and-xml-documents-4j30</link>
      <guid>https://dev.to/rprabhu/jsoup-a-powerful-java-library-for-working-with-html-and-xml-documents-4j30</guid>
      <description>&lt;p&gt;&lt;a href="https://jsoup.org/"&gt;jsoup&lt;/a&gt; is a popular open-source Java library that enables developers to parse, manipulate, and extract data from HTML and XML documents. In this article, we will explore the basics of using jsoup, including parsing HTML documents, selecting and manipulating elements, and updating content in HTML. We'll provide code snippets along the way to help illustrate its capabilities.&lt;/p&gt;

&lt;p&gt;jsoup simplifies working with real-world HTML and XML. It offers an easy-to-use API for URL fetching, data parsing, extraction, and manipulation using DOM API methods, CSS, and xpath selectors.&lt;/p&gt;

&lt;p&gt;jsoup website mentions that it implements the &lt;a href="https://html.spec.whatwg.org/multipage/syntax.html"&gt;WHATWG HTML5&lt;/a&gt; specification, and parses HTML to the same DOM as modern browsers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scrape and parse HTML from a URL, file, or string&lt;/li&gt;
&lt;li&gt;find and extract data, using DOM traversal or CSS selectors&lt;/li&gt;
&lt;li&gt;manipulate the HTML elements, attributes, and text&lt;/li&gt;
&lt;li&gt;clean user-submitted content against a safelist, to prevent XSS attacks output tidy HTML&lt;/li&gt;
&lt;li&gt;jsoup is designed to deal with all varieties of HTML found in the wild; from pristine and validating, to invalid tag-soup; jsoup will create a sensible parse tree.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started with jsoup
&lt;/h2&gt;

&lt;p&gt;To begin using jsoup, you first need to add the library as a dependency in your project. If you are using Maven, include the following in your &lt;code&gt;pom.xml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.jsoup&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;jsoup&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;x.xx.x&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;x.xx.x&lt;/code&gt; is the relevant version, as of this writing it is &lt;code&gt;1.15.3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;or if you are using Gradle, include the following in your &lt;code&gt;build.gradle&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="s1"&gt;'org.jsoup:jsoup:x.xx.x'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Parsing an HTML Document
&lt;/h2&gt;

&lt;p&gt;To parse an HTML document using jsoup, you can use the &lt;code&gt;jsoup.connect()&lt;/code&gt; method followed by the URL of the HTML file or webpage you want to work with. Here's a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jsoup.jsoup&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jsoup.nodes.Document&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;jsoupExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Document&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsoup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://www.example.com"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Continue working with the parsed document&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Selecting and Manipulating Elements
&lt;/h2&gt;

&lt;p&gt;jsoup provides several methods to select and manipulate elements in an HTML or XML document. For example, you can use the &lt;code&gt;select()&lt;/code&gt; method to select elements based&lt;br&gt;
on their tags or attributes, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jsoup.jsoup&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jsoup.nodes.Document&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jsoup.nodes.Element&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jsoup.select.Elements&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;jsoupExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Document&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsoup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://www.example.com"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Select all 'h1' tags in the document&lt;/span&gt;
    &lt;span class="nc"&gt;Elements&lt;/span&gt; &lt;span class="n"&gt;h1Elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"h1"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Update the content of the first 'h1' tag&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Element&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;h1Elements&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;replaceAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"old"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"new"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Updating Content in HTML
&lt;/h2&gt;

&lt;p&gt;In addition to selecting and manipulating elements, you can also update the content of individual elements or the entire document using various methods provided by&lt;br&gt;
jsoup. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jsoup.jsoup&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jsoup.nodes.Document&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jsoup.nodes.Element&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;jsoupExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Document&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsoup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://www.example.com"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Update the content of a specific element&lt;/span&gt;
    &lt;span class="nc"&gt;Element&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;selectFirst&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"h1"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"New Header"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Update the entire document's content&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;newContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"This is the updated content."&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newContent&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;jsoup is a powerful Java library for working with HTML and XML documents, enabling developers to parse, extract data, and manipulate elements efficiently. By using jsoup's simple yet effective APIs, you can save time and effort while producing cleaner, more maintainable code. It can effectively be used in content scraping (of course, without violating any policies or legal requirements) or editing and manipulating the documents in the document store or archive. Happy Coding!&lt;/p&gt;

</description>
      <category>java</category>
      <category>html</category>
      <category>xml</category>
      <category>parsing</category>
    </item>
    <item>
      <title>Guided Tours Solution for Your Web Application</title>
      <dc:creator>Prabhu R</dc:creator>
      <pubDate>Wed, 06 Mar 2024 14:34:48 +0000</pubDate>
      <link>https://dev.to/rprabhu/guided-tours-solution-for-your-web-application-4cja</link>
      <guid>https://dev.to/rprabhu/guided-tours-solution-for-your-web-application-4cja</guid>
      <description>&lt;p&gt;Creating a user-friendly and engaging onboarding experience is crucial for ensuring that new users can effectively navigate any web application. Guided tours are an excellent way to help new users familiarize themselves with the various features of the application. In this article, we will compare five popular JavaScript libraries used for building guided tours in web applications: Shepherd, Bootstrap Tour, driver.js, Tour Guide JS, and Intro.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shepherd
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://shepherdjs.dev/"&gt;Shepherd&lt;/a&gt; is a powerful and customizable open source JavaScript library for creating interactive tours and onboarding experiences in web applications. It uses another open source library &lt;a href="https://floating-ui.com/"&gt;Floating UI&lt;/a&gt; to render the dialog tours. It offers a simple setup process, dynamic content support, the ability to create custom actions and events, and theming and styling too. More importantly, it is responsive too and never goes offscreen on smaller devices. &lt;a href="https://shepherdjs.dev/"&gt;Shepherd&lt;/a&gt; also provides excellent documentation and support, making it a popular choice among developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bootstrap Tour
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://bootstraptour.com/"&gt;Bootstrap Tour&lt;/a&gt; is another open source JavaScript library that focuses on creating guided tours for web applications. It integrates seamlessly with the Bootstrap framework. It offers a wide range of features&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;customizable steps &lt;/li&gt;
&lt;li&gt;keyboard navigation&lt;/li&gt;
&lt;li&gt;progress indicators&lt;/li&gt;
&lt;li&gt;page navigation&lt;/li&gt;
&lt;li&gt;automatic step progressing&lt;/li&gt;
&lt;li&gt;interactive step progress e.g. progress when the user clicks on the page element&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The library hasn\'t been updated since a long time, yet the features are still great!&lt;/p&gt;

&lt;h2&gt;
  
  
  driver.js
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://driverjs.com/"&gt;driver.js&lt;/a&gt; is an open source JavaScript library designed for creating Product tours, highlights, contextual help aand feature adoption. Due to its extensive API, driver.js can be used for a wide range of use cases that includes &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Onboarding the users by explaining how to use the product and answer common questions&lt;/li&gt;
&lt;li&gt;Remove Distractions with the highlights feature and focus user attention on what matters.&lt;/li&gt;
&lt;li&gt;Provide contextual help for users&lt;/li&gt;
&lt;li&gt;Highlight new features and make sure users don't miss them.&lt;/li&gt;
&lt;li&gt;Works on Mobile devices as well.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://driverjs.com/"&gt;driver.js&lt;/a&gt; provides different flavours for its features with demo examples showcased in the site. The list has&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Animated tours &lt;/li&gt;
&lt;li&gt;Non-animated tours &lt;/li&gt;
&lt;li&gt;Async tours&lt;/li&gt;
&lt;li&gt;Tours with Progress&lt;/li&gt;
&lt;li&gt;Overlay styling and more&lt;/li&gt;
&lt;li&gt;Theming &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://driverjs.com/"&gt;driver.js&lt;/a&gt; is actively developed and has a very good documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tour Guide JS
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://tourguidejs.com/"&gt;Tour Guide JS&lt;/a&gt; is a lightweight open source library for creating guided tours in web applications. It offers the following features&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is framework agnostic&lt;/li&gt;
&lt;li&gt;Has Typescript support&lt;/li&gt;
&lt;li&gt;Like &lt;a href="https://shepherdjs.dev/"&gt;Shepherd&lt;/a&gt; this too uses &lt;a href="https://floating-ui.com/"&gt;Floating UI&lt;/a&gt; for navigation&lt;/li&gt;
&lt;li&gt;Provides a lot of options for customization&lt;/li&gt;
&lt;li&gt;Has extensive documentation&lt;/li&gt;
&lt;li&gt;Also supports npm and mentions it to be better that using it directly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Intro.js
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://introjs.com/"&gt;Intro.js&lt;/a&gt; like the others offers a rich set of features such as customizable steps and tooltips, keyboard navigation, theming, progress indicators and more. Like others, this library also has extensive documentation. Intro.js has open source licence under AGPL v3 and a commercial licence with different price plans&lt;/p&gt;

&lt;p&gt;Take a look at these libraries and happy coding your next web application with one of these!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>library</category>
      <category>programming</category>
    </item>
    <item>
      <title>Datafaker: Simplifying Test Data Generation for Java and Kotlin</title>
      <dc:creator>Prabhu R</dc:creator>
      <pubDate>Mon, 04 Dec 2023 15:29:17 +0000</pubDate>
      <link>https://dev.to/rprabhu/datafaker-simplifying-test-data-generation-for-java-and-kotlin-57lf</link>
      <guid>https://dev.to/rprabhu/datafaker-simplifying-test-data-generation-for-java-and-kotlin-57lf</guid>
      <description>&lt;p&gt;In the world of software development, effective testing is crucial to ensure the reliability and functionality of applications. A significant aspect of robust testing is the use of representative and reliable test data. &lt;a href="https://www.datafaker.net/"&gt;Datafaker&lt;/a&gt;, a powerful library for Java and Kotlin, simplifies the process of generating test data. In this article, we'll explore Datafaker and provide code examples for both Java and Kotlin, using the Maven coordinates to get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Datafaker?
&lt;/h2&gt;

&lt;p&gt;Datafaker is a Java and Kotlin library designed to streamline test data generation. It offers a user-friendly interface that makes creating mock data a breeze. Whether you need to generate test data for a database, API endpoints, or other testing purposes, Datafaker is the tool of choice for simplified data generation. It can be used to generate fake data for a variety of purposes, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Testing software&lt;/li&gt;
&lt;li&gt;Creating training data for machine learning models&lt;/li&gt;
&lt;li&gt;Anonymizing data&lt;/li&gt;
&lt;li&gt;Generating mock data for presentations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Features of Datafaker
&lt;/h2&gt;

&lt;p&gt;Datafaker boasts a range of features that make it an indispensable tool for developers and testers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Variety of Data Types:&lt;/strong&gt; Datafaker supports a wide array of data types, including names, addresses, phone numbers, emails, dates, numbers, and more. This versatility ensures you can generate diverse test data for different use cases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fake Data Providers:&lt;/strong&gt; Datafaker has many providers (233 as of 2.0.0) that are grouped under the following groups.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Base (Providers of everyday data)&lt;/li&gt;
&lt;li&gt;Entertainment (Providers for movies, shows, books)&lt;/li&gt;
&lt;li&gt;Food (Providers for different types of food)&lt;/li&gt;
&lt;li&gt;Sport (Providers for different types of sport)&lt;/li&gt;
&lt;li&gt;Videogame (Video game providers)&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customization:&lt;/strong&gt; You have the power to customize data generation by setting specific constraints or formats implementing a Data Provider. For instance, you can define date formats, create data within a specific range, or adhere to specific patterns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiple locales:&lt;/strong&gt; Datafaker allows us to create multiple locales and also mix them easily with other locale data. The easiest way to do so is to create a Faker per locale, and mix between those fakers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Repeatable random results:&lt;/strong&gt; To generate a more predictable and repeatable data, we can provide a seed, and the instantiation of Fake objects will always happen in a predictable way, which can be handy for generating results multiple times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bulk Data Generation:&lt;/strong&gt; Datafaker allows for bulk data generation, making it easy to create extensive datasets for comprehensive testing. These bulk generations can be returned as a Java Collection or Java Streams, however the test needs it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Export/Transform Data:&lt;/strong&gt; The generated data can be easily exported/transformed in multiple formats, such as XML, JSON, CSV, and SQL, ensuring compatibility with various testing and development environments.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are other similar projects like &lt;a href="http://dius.github.io/java-faker/"&gt;Java Faker&lt;/a&gt;, &lt;a href="https://serpro69.github.io/kotlin-faker/"&gt;Kotlin Faker&lt;/a&gt;, &lt;a href="https://devskiller.github.io/jfairy/"&gt;JFairy&lt;/a&gt; which provide similar functionality, however, Datafaker is quite active.&lt;/p&gt;

&lt;p&gt;Now, let's dive into code examples to illustrate how Datafaker can be used for test data generation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Examples
&lt;/h2&gt;

&lt;p&gt;To get started with Datafaker in Java, add the following Maven dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;net.datafaker&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;datafaker&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.0.2&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's look at how you can generate random names, email addresses and phone numbers in Java:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Java Example&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;net.datafaker.Faker&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestDataGeneration&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Faker&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Generate random names&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;fullName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;fullName&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;internet&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;emailAddress&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;phoneNumber&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;phoneNumber&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Generate a collection of names&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; 
            &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;len&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Java code snippet generates a firstName, a lastName, a fullName, an email and a phoneNumber. Followed by generating a collection of 10 names using two Suppliers where one Supplier provides the firstName and the other the lastName.&lt;/p&gt;

&lt;p&gt;The bulk generation can be returned as Streams as well, like in the following code snippet&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; 
            &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;len&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Datafaker also provides a number of features for generating more complex data. For example, you can use Datafaker to generate fake data for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Addresses&lt;/li&gt;
&lt;li&gt;Companies&lt;/li&gt;
&lt;li&gt;Credit cards&lt;/li&gt;
&lt;li&gt;Dates and times&lt;/li&gt;
&lt;li&gt;Locations&lt;/li&gt;
&lt;li&gt;Products&lt;/li&gt;
&lt;li&gt;Services&lt;/li&gt;
&lt;li&gt;Vehicles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To generate more complex data, you can use Datafaker's providers. Providers are classes that generate fake data for a specific type of data. For example, the &lt;code&gt;Address&lt;/code&gt; provider can generate fake addresses, while the &lt;code&gt;Company&lt;/code&gt; provider can generate fake companies.&lt;/p&gt;

&lt;p&gt;Here is an example of how to use Datafaker's &lt;code&gt;Company&lt;/code&gt; provider to generate a fake company profile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;net.datafaker.Faker&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Example&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Faker&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;company&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;catchPhrase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;company&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;catchPhrase&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;website&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;internet&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;domainName&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Name: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Catch phrase: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;catchPhrase&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Website: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;website&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code will generate a fake company profile with a random name, catch phrase, and website.&lt;/p&gt;

&lt;p&gt;For Kotlin, the code is more or less similar except for the Kotlin constructs. &lt;/p&gt;

&lt;p&gt;Efficient testing requires reliable and representative test data, and Datafaker excels at this task. With its intuitive interface and wide array of data generation capabilities, Datafaker proves to be a valuable tool for both developers and testers. Whether you need to generate names, addresses, user data, or any other type of test data, Datafaker is your trusted companion. Give it a try, and experience how it streamlines the testing process, saving you time and effort in the long run.&lt;/p&gt;

&lt;p&gt;To get started with Datafaker, you can find it on Maven Central using the following Maven coordinates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;net.datafaker&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;datafaker&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.0.2&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The documentation in the official website is also comprehensive. Please read it to understand the wide range of options it provides.&lt;/p&gt;

</description>
      <category>java</category>
      <category>library</category>
      <category>mock</category>
      <category>testdata</category>
    </item>
    <item>
      <title>Discovering "Everything": A Powerful File Search Tool</title>
      <dc:creator>Prabhu R</dc:creator>
      <pubDate>Fri, 20 Oct 2023 17:58:21 +0000</pubDate>
      <link>https://dev.to/rprabhu/discovering-everything-a-powerful-file-search-tool-4ocp</link>
      <guid>https://dev.to/rprabhu/discovering-everything-a-powerful-file-search-tool-4ocp</guid>
      <description>&lt;p&gt;Imagine a world where you can instantly find any file on your computer with just a few keystrokes. No more endless clicking through folders or searching through a cluttered desktop. Welcome to the world of "Everything" - a remarkable file search tool that is lean in size and on the resources it uses.&lt;/p&gt;

&lt;p&gt;"Everything" is a free, lightweight, portable and lightning-fast file search utility for Windows. Developed by David Carpenter, Voidtools. This gem of a software is designed to make file searching as efficient and effortless as possible. Moreover, it is portable too, no installation necessary! Let's look at some of the key features&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Instant Search:&lt;/strong&gt; The hallmark feature of "Everything" is its speed. As soon as you start typing in the search bar, it displays results in real-time. It's like having Google Search for your local files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Light on Resources:&lt;/strong&gt; Despite its powerful capabilities, "Everything" is incredibly light on system resources. It won't slow down your computer, even when indexing large drives.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Real-time updates:&lt;/strong&gt; Changes to the file system, like adding new files, deleting files updates the index in real-time&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Regex Support&lt;/strong&gt; For advanced users, "Everything" supports regular expressions, allowing you to create complex search queries with ease.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Content Search:&lt;/strong&gt; It has the ability to search within the contents of the files too!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quick Access:&lt;/strong&gt; You can use custom keyboard shortcuts to access "Everything" from anywhere, enhancing your productivity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easy to use:&lt;/strong&gt; Everything has a simple and intuitive user interface.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;How to Get Started:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Download and Install:&lt;/strong&gt; Visit the &lt;a href="https://www.voidtools.com"&gt;official Voidtools website&lt;/a&gt; to download and install "Everything". You can choose between an installer and a portable version too!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Index Your Drives:&lt;/strong&gt; After installation, "Everything" will index the files on your drives. This initial process might take some time, but the payoff is worth it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Start Searching:&lt;/strong&gt; Once indexing is complete, simply type your query into the search bar, and watch as "Everything" presents you with instant, accurate results.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Organizing Files:&lt;/strong&gt; Easily locate and manage files, even if you can't remember where you saved them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quick Document Retrieval:&lt;/strong&gt; Find important documents, presentations, or spreadsheets in seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cleaning Up Clutter:&lt;/strong&gt; Identify and remove duplicate files or old documents you no longer need.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient Workflows:&lt;/strong&gt; Streamline your workflow by accessing files rapidly, saving you valuable time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a world where digital clutter can overwhelm us, "Everything" comes to the rescue as an indispensable tool for file management and organization. Give it a try, and you'll wonder how you ever managed without it. Download "Everything" today and take control of your digital world like never before.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tools</category>
      <category>search</category>
      <category>windows</category>
    </item>
    <item>
      <title>Story Points - Intent and Effectiveness</title>
      <dc:creator>Prabhu R</dc:creator>
      <pubDate>Sat, 23 Sep 2023 08:43:34 +0000</pubDate>
      <link>https://dev.to/rprabhu/story-points-intent-and-effectiveness-3n7g</link>
      <guid>https://dev.to/rprabhu/story-points-intent-and-effectiveness-3n7g</guid>
      <description>&lt;p&gt;In some companies, "Story Points" have the following two purposes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A convoluted measure for customer billing, the customer won't really know how much effort has been put up for the said amount of story points in the bill.&lt;/li&gt;
&lt;li&gt;A number by which the developer has no idea on how much task he is taking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essentially, story points are an abstract way to define the complexity of a task at hand, usually denoted in terms of the numbers in the Fibonacci Series (natural numbers are acceptable too). The higher the number, the complex the task; so, if the number is large, it implies that it will have to be broken down into smaller manageable pieces.&lt;/p&gt;

&lt;p&gt;Story points was intended to help the developers provide an effort estimate of the tasks without committing to the number of days/hours which is usually hard or not accurate. However, it has turned out in a way that it masks a direct way to calculate the effort that was involved in Time &amp;amp; Material Projects.&lt;/p&gt;

&lt;p&gt;It is also to help in building a clear and expressive burnout charts that show how big the tasks were that the team had worked on.&lt;/p&gt;

&lt;p&gt;Sometimes, the story points are twisted so much that the stories in them are just made up and the points don't really matter. Another problem with story points is that the management would expect the team to achieve the same amount of story points or more in each sprint, under the name of "increased productivity", even if they are understaffed. On the contrary, the team inflates the story points just to level it with their previous sprints, so that they will not be questioned by the management. Hence, neither the manager nor the team would be able to tell the exact amount of work done. They will have to settle down with the figures knowing each one is cheating the other.&lt;/p&gt;

&lt;p&gt;Some interesting dialogues we usually hear on story&lt;br&gt;
points.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"The customer won’t agree for that many story points bring it down further…"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Do the story points include the testing effort?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Please move the incomplete story points to the next sprint..."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Excerpt from my book - &lt;a href="https://notionpress.com/read/excel-in-it"&gt;Excel in IT&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>agile</category>
      <category>scrum</category>
      <category>storypoints</category>
      <category>projectmanagement</category>
    </item>
    <item>
      <title>Code-athon, Code marathon or Hackthon: Is it good?</title>
      <dc:creator>Prabhu R</dc:creator>
      <pubDate>Fri, 08 Sep 2023 15:35:09 +0000</pubDate>
      <link>https://dev.to/rprabhu/code-athon-code-marathon-or-hackthon-is-it-good-2eoa</link>
      <guid>https://dev.to/rprabhu/code-athon-code-marathon-or-hackthon-is-it-good-2eoa</guid>
      <description>&lt;p&gt;In the ever-evolving landscape of tech-driven workplaces, companies are increasingly adopting unique approaches to foster innovation, collaboration, and rapid problem-solving. &lt;/p&gt;

&lt;p&gt;One such approach gaining popularity is the code-athon, code marathon or hackathon — a structured event where teams come together in the office for a concentrated burst of coding, creativity, and camaraderie. Typically, this happens over a duration of 48 to 72 hours at a stretch.&lt;/p&gt;

&lt;p&gt;In some companies, this has become more of a monthly or a bimonthly ritual. These code marathons definitely have a benefit but they also have a disadvantage. &lt;/p&gt;

&lt;p&gt;While these events have their merits, they also come with their own set of challenges. Let's see the pros and cons of these code marathons&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Innovation Boost:&lt;/strong&gt; Code-athons encourage teams to think outside the box, experiment with new ideas, and innovate quickly. These bursts of creativity can lead to groundbreaking solutions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Team Building:&lt;/strong&gt; Bringing teams together for intensive coding sessions fosters collaboration and strengthens team bonds. It promotes a sense of belonging and shared achievement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Accelerated Development:&lt;/strong&gt; Code-athons are excellent for rapidly developing and prototyping new features or products, helping companies stay competitive in fast-paced markets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Skill Enhancement:&lt;/strong&gt; Participants often learn new skills, tools, and technologies during these events, which can benefit both their personal growth and the company's technological prowess.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Problem Solving:&lt;/strong&gt; Code-athons provide a platform to address complex problems that may have been lingering, offering fresh perspectives and innovative solutions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Burnout Risk:&lt;/strong&gt; Code-athons at regular intervals can lead to burnout if not managed properly. Intense, recurring events may cause fatigue and negatively impact overall productivity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quality vs. Speed:&lt;/strong&gt; The emphasis on speed and deadlines may prioritize quantity over quality. Rushed code can lead to technical debt and long-term maintenance challenges.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inclusivity Concerns:&lt;/strong&gt; Not all team members may thrive in such high-pressure environments. Code-athons can unintentionally exclude those who work better at a steady, sustainable pace.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sustainability:&lt;/strong&gt; Maintaining the frequency of code-athons can be challenging in the long run. Teams may struggle to sustain enthusiasm and participation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Allocation:&lt;/strong&gt; These events require time and resources, potentially diverting focus from ongoing projects and strategic initiatives.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Doing it once in a while definitely has its benefits, but making it a regular ritual results in the team getting exhausted, become less motivated and counter-productive.&lt;/p&gt;

&lt;p&gt;In conclusion, code-athons can be a powerful tool for boosting innovation and team cohesion. However, they should be approached with care and consideration for their potential downsides. Striking the right balance between regular code-athons and everyday work is key. Ultimately, the success of such rituals lies in the company's ability to manage the intensity, promote a culture of inclusivity, and ensure that the outcomes align with the organization's long-term goals. When done thoughtfully, code-athons can be a driving force behind a company's innovation and growth, however, overdoing it can become detrimental to the entire organization.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>practice</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>TypeScript: To be or not to be</title>
      <dc:creator>Prabhu R</dc:creator>
      <pubDate>Fri, 08 Sep 2023 15:12:46 +0000</pubDate>
      <link>https://dev.to/rprabhu/typescript-to-be-or-not-to-be-53kg</link>
      <guid>https://dev.to/rprabhu/typescript-to-be-or-not-to-be-53kg</guid>
      <description>&lt;p&gt;Recently, there has been a noticeable trend where some individuals and organizations have announced their decision to drop &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt; from their supported stack. Some have done it with a reason, but some want to do it for the drama. While it's entirely valid for teams to reevaluate their technology choices, it's essential to emphasize the significance of constructive and well-informed discussions, especially when it comes to a versatile language like TypeScript.&lt;/p&gt;

&lt;p&gt;Similarly, the once hailed jQuery was suddenly trampled like it was a sin to use jQuery in projects. This sort of a behaviour has been seen with other languages as well - Java, for example. People have been telling that &lt;strong&gt;&lt;em&gt;"Java is dead"&lt;/em&gt;&lt;/strong&gt; for a very long time; but Java has been growing strong ever since. Likewise, R programmers were being mocked that they are rare than white elephants. After the machine learning buzz took off, many started learning and also praised R.&lt;/p&gt;

&lt;p&gt;Though I haven't used TypeScript extensively, I can see how the language filled the gap where JavaScript had a shortfall and how it evolved to being adopted by many frameworks and libraries. Here are some of my observations in the context of TypeScript:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. TypeScript's Strengths:&lt;/strong&gt; TypeScript has gained popularity for its strong typing system, improved developer tooling, and enhanced code maintainability. It's essential to acknowledge these strengths and consider the reasons why it became a part of your tech stack in the first place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Guarding Against the "Sheep Mentality":&lt;/strong&gt; It's crucial to guard against the "sheep mentality," where decisions are made without considering the pros and cons. Dropping TypeScript simply because others are doing so without thoughtful evaluation may lead to missed opportunities and challenges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Continuous Improvement:&lt;/strong&gt; Like any technology, TypeScript continues to evolve. The TypeScript team actively listens to feedback and consistently releases updates to address concerns and enhance the language's capabilities. Engaging in discussions and contributing to its development can lead to positive changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Project-Specific Considerations:&lt;/strong&gt; Technology choices should align with the specific needs and goals of your projects. What works for one may not work for another. It's crucial to evaluate TypeScript within the context of your projects and make informed decisions accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Migration Challenges:&lt;/strong&gt; Abruptly dropping TypeScript can lead to migration challenges, increased development costs, and potential disruptions to ongoing projects. A well-thought-out transition plan, driven by constructive discussions, can help mitigate these challenges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Learning and Collaboration:&lt;/strong&gt; TypeScript has a vibrant and supportive community. Engaging in respectful conversations, sharing experiences, and seeking advice from experienced TypeScript developers can enhance your team's knowledge and foster collaboration.&lt;/p&gt;

&lt;p&gt;TypeScript, like any technology, deserves thoughtful consideration and open dialogue. While it's acceptable to reassess your tech stack, it's crucial to do so with respect for the language's strengths and an understanding of the broader context. Constructive conversations not only benefit your team but also contribute to the continuous improvement of TypeScript and the tech community as a whole. Let's remember that the tech world thrives when we approach challenges with curiosity, collaboration, and a willingness to learn, rather than following the herd blindly.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
