<?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: lucasnscr</title>
    <description>The latest articles on DEV Community by lucasnscr (@lucasnscr).</description>
    <link>https://dev.to/lucasnscr</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%2F786078%2Ff11f942a-d8fc-4be7-a0a7-d7ffa198fc7f.jpeg</url>
      <title>DEV Community: lucasnscr</title>
      <link>https://dev.to/lucasnscr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucasnscr"/>
    <language>en</language>
    <item>
      <title>Customer Support Agent with ADK and LangGraph</title>
      <dc:creator>lucasnscr</dc:creator>
      <pubDate>Mon, 26 Jan 2026 14:56:34 +0000</pubDate>
      <link>https://dev.to/lucasnscr/customer-support-agent-with-adk-and-langgraph-4k5n</link>
      <guid>https://dev.to/lucasnscr/customer-support-agent-with-adk-and-langgraph-4k5n</guid>
      <description>&lt;h1&gt;
  
  
  Customer Support Agent
&lt;/h1&gt;

&lt;p&gt;Customer support agent via WhatsApp with Jira integration, built with Python, FastAPI, LangGraph, and Redis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│    WhatsApp     │────▶│     FastAPI     │────▶│   AgentRunner   │
│   (Webhook)     │     │   /webhooks     │     │   (ADK Style)   │
└─────────────────┘     └─────────────────┘     └────────┬────────┘
│
▼
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│      Redis      │◀───▶│   StateStore    │◀───▶│    LangGraph    │
│   (Sessions)    │     │                 │     │   StateGraph    │
└─────────────────┘     └─────────────────┘     └────────┬────────┘
│
┌───────────────┼───────────────┐
▼               ▼               ▼
┌────────────┐  ┌────────────┐  ┌────────────┐
│ CustomerDB │  │    Jira    │  │  Parsing   │
│   (Tool)   │  │   (Tool)   │  │  (Utils)   │
└────────────┘  └────────────┘  └────────────┘

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conversational Flow
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Customer] “Hi”
│
▼
[Agent] “Hi! To help you, please send me your CNPJ.”
│
▼
[Customer] “11.111.111/0001-91”
│
▼
[System] Validates CNPJ in the database
│
├─── Invalid CNPJ ──▶ “I couldn’t find an active account. Please confirm the number.”
│                           │
│                           └──▶ [Back to requesting CNPJ]
│
└─── Valid CNPJ ──▶ “Perfect! Tell me the product and describe your request.”
│
▼
[Customer] “Product: ERP, Request: error in the report”
│
▼
[System] Creates ticket in Jira
│
▼
[Agent] “✅ Request created: SUP-123”

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.12+&lt;/li&gt;
&lt;li&gt;Docker and Docker Compose&lt;/li&gt;
&lt;li&gt;Poetry (dependency manager)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Clone the repository
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;customer-support-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Install dependencies
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install Poetry (if needed)&lt;/span&gt;
curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://install.python-poetry.org | python3 -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Install dependencies
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Configure environment variables&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create a .env file at the root of the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Redis
REDIS_URL=redis://localhost:6379/0

# Jira
JIRA_BASE_URL=https://your-domain.atlassian.net
JIRA_EMAIL=your-email@example.com
JIRA_API_TOKEN=your-api-token
JIRA_PROJECT_KEY=SUP
JIRA_ISSUE_TYPE=Task

# WhatsApp (optional)
WHATSAPP_PROVIDER=cloudapi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start the services&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Start Redis and the application
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;

&lt;span class="c"&gt;# Or start only Redis (for local development)&lt;/span&gt;
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt; redis

&lt;span class="c"&gt;# Run the application locally&lt;/span&gt;
poetry run uvicorn app.main:app &lt;span class="nt"&gt;--reload&lt;/span&gt; &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Testing with cURL
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Health check&lt;/span&gt;
curl http://localhost:8000/health

&lt;span class="c"&gt;# Simulate WhatsApp message - Greeting&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/webhooks/whatsapp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"from":"+5511999999999","text":"hi"}'&lt;/span&gt;

&lt;span class="c"&gt;# Send valid CNPJ&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/webhooks/whatsapp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"from":"+5511999999999","text":"11111111000191"}'&lt;/span&gt;

&lt;span class="c"&gt;# Send product and request&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/webhooks/whatsapp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"from":"+5511999999999","text":"Product: ERP System, Request: error when generating report"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;/p&gt;
&lt;h3&gt;
  
  
  Valid CNPJs for testing (mock)
&lt;/h3&gt;

&lt;p&gt;CNPJ    Name    Status&lt;br&gt;
11111111000191  Demo Client Ltd.    Active&lt;br&gt;
22222222000191  Test Company S.A.   Active&lt;br&gt;
33333333000191  Inactive Company    Inactive&lt;/p&gt;

&lt;p&gt;API Endpoints&lt;/p&gt;

&lt;p&gt;Method  Endpoint    Description&lt;br&gt;
GET /health Health check&lt;br&gt;
POST    /webhooks/whatsapp  Receives WhatsApp messages&lt;br&gt;
GET /sessions/{phone}   Retrieves session state&lt;br&gt;
DELETE  /sessions/{phone}   Removes session&lt;/p&gt;

&lt;p&gt;Tests&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run all tests&lt;/span&gt;
poetry run pytest

&lt;span class="c"&gt;# Run with coverage&lt;/span&gt;
poetry run pytest &lt;span class="nt"&gt;--cov&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;app

&lt;span class="c"&gt;# Run a specific test&lt;/span&gt;
poetry run pytest tests/test_graph_flow.py &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;customer-support-agent/
├── app/
│   ├── main.py                    # FastAPI webhook
│   ├── settings.py                # Config via env vars
│   └── agent/
│       ├── runner.py              # AgentRunner (ADK style)
│       ├── graph.py               # LangGraph StateGraph
│       ├── state.py               # SupportState TypedDict
│       ├── nodes.py               # Node functions
│       ├── tools/
│       │   ├── customer_db.py     # Customer validation (mock)
│       │   └── jira.py            # Jira REST integration
│       └── utils/
│           ├── parsing.py         # CNPJ, product, request parsing
│           └── store.py           # Redis state store
├── tests/
│   └── test_graph_flow.py         # Flow tests
├── docker-compose.yml
├── Dockerfile
├── pyproject.toml
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Jira Configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating an API Token
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://id.atlassian.com/manage-profile/security/api-tokens" rel="noopener noreferrer"&gt;https://id.atlassian.com/manage-profile/security/api-tokens&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Click “Create API token”&lt;/li&gt;
&lt;li&gt;Copy the token and add it to the .env&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Creating the Project
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a project in Jira (e.g., “SUP” for Support)&lt;/li&gt;
&lt;li&gt;Configure the issue type (Task, Bug, etc.)&lt;/li&gt;
&lt;li&gt;Update the variables JIRA_PROJECT_KEY and JIRA_ISSUE_TYPE&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  WhatsApp Integration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  WhatsApp Cloud API
&lt;/h3&gt;

&lt;p&gt;Configure the webhook URL in Meta Business:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://your-domain.com/webhooks/whatsapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Twilio
&lt;/h3&gt;

&lt;p&gt;Configure the webhook URL in the Twilio Console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://your-domain.com/webhooks/whatsapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/lucasnscr/customer-support-agent" rel="noopener noreferrer"&gt;Repository URL&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>fastapi</category>
      <category>python</category>
    </item>
    <item>
      <title>Quarkus LangChain4j Book Recommendation System</title>
      <dc:creator>lucasnscr</dc:creator>
      <pubDate>Mon, 14 Jul 2025 23:12:50 +0000</pubDate>
      <link>https://dev.to/lucasnscr/quarkus-langchain4j-book-recommendation-system-2cbo</link>
      <guid>https://dev.to/lucasnscr/quarkus-langchain4j-book-recommendation-system-2cbo</guid>
      <description>&lt;h1&gt;
  
  
  Quarkus Book Recommendation System
&lt;/h1&gt;

&lt;p&gt;An intelligent book recommendation system built with &lt;strong&gt;Quarkus&lt;/strong&gt; and &lt;strong&gt;LangChain4j&lt;/strong&gt;, demonstrating the power of AI to personalize reading experiences. The system uses multiple AI providers (&lt;strong&gt;OpenAI&lt;/strong&gt;, &lt;strong&gt;Mistral AI&lt;/strong&gt;, and &lt;strong&gt;Ollama&lt;/strong&gt;) to deliver personalized recommendations based on user profiles and reading history.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lucasnscr/book-recommendation" rel="noopener noreferrer"&gt;Repository&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;Multi-AI Support&lt;/strong&gt;: Switch between OpenAI, Mistral AI, and Ollama&lt;/li&gt;
&lt;li&gt;📚 &lt;strong&gt;Personalized Recommendations&lt;/strong&gt;: AI analyzes preferences and history to suggest books&lt;/li&gt;
&lt;li&gt;🧠 &lt;strong&gt;Conversational Memory&lt;/strong&gt;: Maintains context for personalized interactions&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Intelligent Search&lt;/strong&gt;: AI tools to search for books by multiple criteria&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Pattern Analysis&lt;/strong&gt;: AI analyzes reading habits and suggests diversification&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;Similar Recommendations&lt;/strong&gt;: Finds similar books based on specific titles&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;Quarkus Performance&lt;/strong&gt;: Fast startup and low memory footprint&lt;/li&gt;
&lt;li&gt;🔧 &lt;strong&gt;Simple Configuration&lt;/strong&gt;: Environment variable-based configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;h2&gt;
  
  
  📦 Architecture and Tool Calling with LangChain4j
&lt;/h2&gt;

&lt;p&gt;This system demonstrates advanced usage of the &lt;strong&gt;Tool Calling&lt;/strong&gt; pattern with Quarkus and LangChain4j, integrating AI with external tools and databases. This approach allows language models to access APIs and local repositories to deliver personalized responses based on real-time and accurate data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integration with @Tool
&lt;/h3&gt;

&lt;p&gt;We use the &lt;code&gt;@Tool&lt;/code&gt; annotation to expose Java methods as tools that can be accessed by the AI model. This enables the AI to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query books stored in the database via JPA (Panache).&lt;/li&gt;
&lt;li&gt;Access user preferences and reading history.&lt;/li&gt;
&lt;li&gt;Perform filtering and smart analysis using real business logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example of a Service with AI Tools
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RegisterAiService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;BookSearchTools&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="nc"&gt;UserProfileTools&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;BookRecommendationService&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="sh"&gt;"""
    Based on my preferences, which books do you recommend?
    """&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;recommendBooksForUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;userId&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;h3&gt;
  
  
  Output Validation Guardrails
&lt;/h3&gt;

&lt;p&gt;You can apply custom validations to the model’s responses using &lt;code&gt;@OutputGuardrails&lt;/code&gt;, ensuring result format, safety, and consistency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging and Observability
&lt;/h3&gt;

&lt;p&gt;Quarkus allows detailed logging of model interactions and external API calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;quarkus.langchain4j.log-requests&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;quarkus.langchain4j.log-responses&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Automated Testing with Quarkus
&lt;/h3&gt;

&lt;p&gt;To ensure reliability, endpoints are tested using &lt;code&gt;quarkus-junit5&lt;/code&gt; along with mocked dependencies via &lt;code&gt;quarkus-junit5-mockito&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;This addition highlights how your system uses Tool Calling robustly and aligns with modern intelligent agent development practices.&lt;/p&gt;

&lt;p&gt;The system uses the &lt;strong&gt;AI Tools&lt;/strong&gt; pattern from LangChain4j, allowing the AI to access database data and perform complex operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────┐    ┌──────────────────────┐    ┌─────────────────────┐
│   REST Client   │───▶│ RecommendationController │───▶│BookRecommendationService│
└─────────────────┘    └──────────────────────┘    └─────────────────────┘
                       ┌──────────────────────┐    ┌─────────────────────┐
                       │   BookController     │───▶│   BookDataService   │
                       └──────────────────────┘    └─────────────────────┘
                                                           │
                                              ┌────────────┼────────────┐
                                              │            │            │
                                         ┌────▼────┐ ┌────▼────┐ ┌─────▼──────┐
                                         │  Book   │ │  User   │ │   Config   │
                                         │ Search  │ │ Profile │ │   Class    │
                                         │ Tools   │ │ Tools   │ └─────┬──────┘
                                         └────┬────┘ └────┬────┘       │
                                              │           │            │
                                    ┌─────────▼───┐   ┌───▼────────┐   │
                                    │    Book     │   │    User    │   │
                                    │ Repository  │   │Repositories│   │
                                    └─────────────┘   └────────────┘   │
                                              │                        │
                                         ┌────▼────┐                   │
                                         │   H2    │                   │
                                         │Database │                   │
                                         └─────────┘                   │
                                                                       │
                                              ┌────────────────────────▼────┐
                                              │         LangChain4j         │
                                              │        AI Providers         │
                                              └────────────────────────────┘  
                                                           │
                                        ┌──────────────────┼──────────────────┐
                                        │                  │                  │
                                ┌───────▼────────┐ ┌───────▼────────┐ ┌──────▼───────┐
                                │     OpenAI     │ │   Mistral AI   │ │    Ollama    │
                                │   (gpt-4o-mini)│ │ (mistral-small)│ │   (llama3.2) │
                                └────────────────┘ └────────────────┘ └──────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Java 21 or higher&lt;/li&gt;
&lt;li&gt;Maven 3.8+ or Gradle&lt;/li&gt;
&lt;li&gt;Choose at least one AI provider:&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  OpenAI Configuration
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create an account at &lt;a href="https://platform.openai.com/" rel="noopener noreferrer"&gt;OpenAI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Generate an API key in the API keys section&lt;/li&gt;
&lt;li&gt;Set the environment variable &lt;code&gt;OPEN_AI_TOKEN&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Mistral AI Configuration
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create an account at &lt;a href="https://console.mistral.ai/" rel="noopener noreferrer"&gt;Mistral AI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Generate an API key in your dashboard&lt;/li&gt;
&lt;li&gt;Set the environment variable &lt;code&gt;MISTRAL_AI_TOKEN&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Ollama Configuration
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install Ollama from &lt;a href="https://ollama.ai/" rel="noopener noreferrer"&gt;ollama.ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Start the Ollama service: &lt;code&gt;ollama serve&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Download a model: &lt;code&gt;ollama pull llama3.2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Ensure Ollama is running at &lt;code&gt;http://localhost:11434&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Selecting the AI Provider
&lt;/h3&gt;

&lt;p&gt;Set the AI provider using the &lt;code&gt;AI_MODEL_PROVIDER&lt;/code&gt; environment variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# For OpenAI (default)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AI_MODEL_PROVIDER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;openai
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPEN_AI_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-openai-key

&lt;span class="c"&gt;# For Mistral AI&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AI_MODEL_PROVIDER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mistral
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MISTRAL_AI_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-mistral-key

&lt;span class="c"&gt;# For Ollama&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AI_MODEL_PROVIDER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Clone the Repository
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;repository-url&amp;gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;quarkus-book-recommendation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Set Up Your AI Provider
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Option A: Using OpenAI&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AI_MODEL_PROVIDER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;openai
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPEN_AI_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-real-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Option B: Using Mistral AI&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AI_MODEL_PROVIDER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mistral
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MISTRAL_AI_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-real-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Option C: Using Ollama&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start Ollama first&lt;/span&gt;
ollama serve

&lt;span class="c"&gt;# In another terminal, download a model&lt;/span&gt;
ollama pull llama3.2

&lt;span class="c"&gt;# Set up the environment&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AI_MODEL_PROVIDER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Run the Application
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Development Mode (with hot reload):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw quarkus:dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Production Mode:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw clean package
java &lt;span class="nt"&gt;-jar&lt;/span&gt; target/quarkus-app/quarkus-run.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application will start at &lt;code&gt;http://localhost:8080&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  API Endpoints
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Book Generation Endpoints
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Generate Book List by Genre
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Endpoint:&lt;/strong&gt; &lt;code&gt;GET /api/books/generate/{genre}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Generates a list of 10 books using AI for the specified genre.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET &lt;span class="s2"&gt;"http://localhost:8080/api/books/generate/fantasy?sessionId=user123"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Get Book by ID
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Endpoint:&lt;/strong&gt; &lt;code&gt;GET /api/books/{sessionId}/{id}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Retrieves a specific book by ID using AI with chat memory capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET http://localhost:8080/api/books/user123/1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Recommendation Endpoints
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Personalized User Recommendations
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Endpoint:&lt;/strong&gt; &lt;code&gt;GET /api/recommendations/user/{userId}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Uses AI with LangChain4j tools to analyze the user profile and recommend personalized books.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET http://localhost:8080/api/recommendations/user/1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Based on your profile and reading history, here are 5 perfect recommendations for you:

1. **Foundation** by Isaac Asimov
   - Perfectly matches your love of epic science fiction like Dune
   - Classic series with complex worldbuilding and deep political themes

2. **The Name of the Wind** by Patrick Rothfuss
   - Epic fantasy with immersive storytelling, similar to Madeline Miller's style
   - Poetic prose and exceptional character development

[...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Find Similar Books
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Endpoint:&lt;/strong&gt; &lt;code&gt;GET /api/recommendations/similar&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Finds similar books based on a specific title and author.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET &lt;span class="s2"&gt;"http://localhost:8080/api/recommendations/similar?title=Dune&amp;amp;author=Frank Herbert"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Recommendations by Genre and Criteria
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Endpoint:&lt;/strong&gt; &lt;code&gt;GET /api/recommendations/genre/{genre}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Recommends books based on genre and specific criteria.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET &lt;span class="s2"&gt;"http://localhost:8080/api/recommendations/genre/science-fiction?minRating=4.0&amp;amp;language=English&amp;amp;yearAfter=2010"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Reading Pattern Analysis
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Endpoint:&lt;/strong&gt; &lt;code&gt;GET /api/recommendations/analysis/{userId}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Analyzes the user's reading patterns and suggests diversification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET http://localhost:8080/api/recommendations/analysis/1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  AI Tools
&lt;/h2&gt;

&lt;p&gt;The system demonstrates advanced AI capabilities using LangChain4j tools:&lt;/p&gt;

&lt;h3&gt;
  
  
  Book Search Tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Search by Genre&lt;/strong&gt;: Retrieve books by category&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search by Author&lt;/strong&gt;: Find books by specific authors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search by Rating&lt;/strong&gt;: Filter books by minimum rating&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search by Language&lt;/strong&gt;: Filter books by language&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search by Year&lt;/strong&gt;: Find books by publication period&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  User Profile Tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User Preferences&lt;/strong&gt;: Access stored reading preferences&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reading History&lt;/strong&gt;: Retrieve books read by the user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pattern Analysis&lt;/strong&gt;: Identify trends in reading habits&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  AI Service Integration
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;BookRecommendationService&lt;/code&gt; combines both sets of tools to provide intelligent analysis:&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="nd"&gt;@RegisterAiService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;BookSearchTools&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="nc"&gt;UserProfileTools&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;BookRecommendationService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// AI can automatically call tools to analyze preferences&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;recommendBooksForUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// AI can find similar books using multiple criteria&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;findSimilarBooks&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;bookTitle&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;author&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;
  
  
  Technology Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quarkus 3.24.3&lt;/strong&gt; - Supersonic Subatomic Java Framework&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LangChain4j&lt;/strong&gt; - Java library for building AI applications

&lt;ul&gt;
&lt;li&gt;OpenAI Integration (v1.0.2)&lt;/li&gt;
&lt;li&gt;Mistral AI Integration (v1.0.2)&lt;/li&gt;
&lt;li&gt;Ollama Integration (v1.0.2)&lt;/li&gt;
&lt;li&gt;Support for AI Tools and Agents&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;JAX-RS (Quarkus REST)&lt;/strong&gt; - RESTful web services&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Hibernate ORM with Panache&lt;/strong&gt; - Database operations&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;H2 Database&lt;/strong&gt; - In-memory database for development&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Jackson&lt;/strong&gt; - JSON processing&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;CDI&lt;/strong&gt; - Dependency injection&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Development
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Project Structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/main/java/com/example/books/
├── resources/
│   ├── BookController.java              # REST endpoints for books
│   └── RecommendationController.java    # Recommendation endpoints
├── service/
│   ├── BookDataService.java             # AI service interface
│   └── BookRecommendationService.java   # AI service with tools
├── model/
│   ├── Book.java                        # Book data model
│   ├── UserPreference.java              # User preferences
│   └── ReadingHistory.java              # Reading history
├── repository/
│   ├── BookRepository.java              # Database operations for books
│   ├── UserPreferenceRepository.java    # Preference operations
│   └── ReadingHistoryRepository.java    # History operations
├── tools/
│   ├── BookSearchTools.java             # Book search tools
│   └── UserProfileTools.java            # User profile tools
└── api/
    └── BookListResponse.java            # API response models
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running Tests
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Development with Hot Reload
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw quarkus:dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enables hot reload—changes to your code will be automatically reflected without restarting the application.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Personalized Recommendations&lt;/strong&gt;: AI analyzes the user's complete profile&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intelligent Search&lt;/strong&gt;: AI tools for complex database queries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pattern Analysis&lt;/strong&gt;: AI identifies trends and suggests diversification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversational Memory&lt;/strong&gt;: Context maintained between interactions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Generation&lt;/strong&gt;: AI creates realistic book data by genre&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Fork the repository&lt;/li&gt;
&lt;li&gt;Create a feature branch&lt;/li&gt;
&lt;li&gt;Make your changes&lt;/li&gt;
&lt;li&gt;Add tests if applicable&lt;/li&gt;
&lt;li&gt;Submit a pull request&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;p&gt;This project is open source and available under the &lt;a href="https://dev.toLICENSE"&gt;MIT License&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Happy reading with AI! 📚🤖&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>quarkus</category>
      <category>langchain</category>
      <category>genai</category>
    </item>
    <item>
      <title>MCP and Spring AI</title>
      <dc:creator>lucasnscr</dc:creator>
      <pubDate>Wed, 26 Mar 2025 11:46:53 +0000</pubDate>
      <link>https://dev.to/lucasnscr/mcp-and-spring-ai-1dj4</link>
      <guid>https://dev.to/lucasnscr/mcp-and-spring-ai-1dj4</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/lucasnscr" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F786078%2Ff11f942a-d8fc-4be7-a0a7-d7ffa198fc7f.jpeg" alt="lucasnscr"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/lucasnscr/mcp-protocol-with-spring-ai-l9b" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;MCP Protocol with Spring AI&lt;/h2&gt;
      &lt;h3&gt;lucasnscr ・ Mar 20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#mcp&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#spring&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#ai&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>mcp</category>
      <category>spring</category>
      <category>ai</category>
    </item>
    <item>
      <title>MCP Protocol with Spring AI</title>
      <dc:creator>lucasnscr</dc:creator>
      <pubDate>Thu, 20 Mar 2025 11:41:39 +0000</pubDate>
      <link>https://dev.to/lucasnscr/mcp-protocol-with-spring-ai-l9b</link>
      <guid>https://dev.to/lucasnscr/mcp-protocol-with-spring-ai-l9b</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Implementing a Real-World Credit Score Verification System&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This project leverages &lt;strong&gt;Spring AI&lt;/strong&gt; with &lt;strong&gt;Tool Calling&lt;/strong&gt; capabilities to orchestrate multiple AI-driven tools, managed by the &lt;strong&gt;Qwen 2.5 model from Alibaba Cloud&lt;/strong&gt;. The solution is seamlessly integrated with &lt;strong&gt;Slack via the Model Context Protocol (MCP)&lt;/strong&gt;, enabling efficient and intelligent credit score verification for specific users and automatically posting the results in a designated channel within the workspace.&lt;/p&gt;

&lt;p&gt;Before we start to explain MCP, I think is important we start the discuss why almost times I tried use &lt;strong&gt;OpenSource&lt;/strong&gt; technologies and why this time I choose &lt;strong&gt;Qwen 2.5&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Open Source LLMs?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open-source LLMs offer a blend of cost savings, adaptability, transparency, community-driven enhancements, scalability, and data control, making them a viable and often preferable alternative to proprietary models.​&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cost-Effectiveness: Open-source LLMs eliminate licensing fees, reducing initial expenses. While operational costs like infrastructure remain, the absence of proprietary fees makes advanced AI capabilities more accessible, especially for smaller organizations. ​&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Customization and Flexibility: These models can be fine-tuned to specific business needs, allowing for tailored applications across various industries. This adaptability enables seamless integration into existing systems, enhancing operational efficiency. ​&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transparency and Security: Access to the source code provides insights into the model's architecture and training data, fostering trust and aiding in audits for ethical and legal compliance. This transparency ensures robust and accountable AI applications. ​&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Community Support and Collaboration: The open-source nature encourages contributions from a diverse set of developers and researchers, leading to continuous improvements and innovation. This collaborative environment accelerates advancements and ensures the models remain up-to-date with emerging trends. ​&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scalability: Open-source LLMs allow organizations to scale operations according to their requirements, such as handling large volumes of data or expanding into new applications and markets. ​&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Privacy and Independence: Deploying open-source models locally ensures that sensitive data remains within an organization's infrastructure, reducing the risk of data leaks and unauthorized access. This autonomy allows for greater control over data management and compliance with privacy regulations. ​&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Qwen 2.5
&lt;/h2&gt;

&lt;p&gt;Qwen 2.5 is an advanced language model developed by Alibaba Cloud, designed to handle a wide range of artificial intelligence tasks. This model stands out for its code generation capabilities, multilingual support, and extensive context processing, making it a versatile tool for various applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages of Using Qwen 2.5 in Implementations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Versatility:&lt;/strong&gt; With multilingual support and advanced capabilities in code generation and long-context processing, Qwen 2.5 can be applied across various industries, from software development to education and research.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cost Efficiency:&lt;/strong&gt; Compared to other AI models on the market, Qwen 2.5 offers a competitive pricing structure, making it an attractive option for startups and companies seeking high-performance AI solutions without a significant investment.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Processing Large Volumes of Data:&lt;/strong&gt; Its ability to handle extensive contexts allows Qwen 2.5 to process long and complex texts without losing coherence, which is essential for tasks requiring detailed analysis and deep understanding.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration with Cloud Services:&lt;/strong&gt; The model is optimized for cloud computing environments, enabling efficient scalability and integration with other Alibaba Cloud services, simplifying implementation in existing infrastructures.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Community and Support:&lt;/strong&gt; As an open-source model, Qwen 2.5 benefits from an active community of developers, providing additional resources, support, and continuous updates, which is advantageous for organizations looking for robust and up-to-date AI solutions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://arxiv.org/abs/2412.15115" rel="noopener noreferrer"&gt;Qwen article&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct" rel="noopener noreferrer"&gt;Qwen Hugging Face Page&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is MCP Protocol?
&lt;/h2&gt;

&lt;p&gt;The Model Context Protocol (MCP) is an open standard designed to facilitate the integration of AI systems with various external tools, databases, and services. It acts as a universal connector for AI applications, much like USB-C for devices, enabling seamless interactions between Large Language Models (LLMs) and different data sources.&lt;/p&gt;

&lt;p&gt;MCP eliminates the need for multiple custom API integrations by providing a single, standardized method for AI tools to access and interact with external data dynamically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Use MCP Instead of Traditional APIs?&lt;/strong&gt;&lt;br&gt;
Traditional API-based integrations require separate connections for each external service, meaning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each API has unique authentication and documentation.&lt;/li&gt;
&lt;li&gt;Developers need to write and maintain custom code for every integration.&lt;/li&gt;
&lt;li&gt;Communication is often one-way, limiting real-time interactions.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;MCP solves these issues by offering:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single, standardized integration instead of multiple separate APIs.&lt;/li&gt;
&lt;li&gt;Real-time, two-way communication, allowing AI models to not only retrieve data but also trigger actions dynamically.&lt;/li&gt;
&lt;li&gt;Dynamic discovery of tools, meaning AI models can access new services without needing manual reconfiguration.&lt;/li&gt;
&lt;li&gt;Easier scalability, as developers can connect multiple data sources with minimal additional effort.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;Who Created MCP?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Originally developed by Anthropic, MCP is now an open-source standard being adopted by various companies and developers, aiming to establish a universal method for AI-tool interactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How MCP Works – Architecture Overview&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MCP follows a client-server architecture, consisting of three main components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP Hosts – AI-driven applications (e.g., Claude, AI-powered IDEs) that need access to external tools.&lt;/li&gt;
&lt;li&gt;MCP Clients – Maintain one-to-one connections with MCP servers to exchange data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbe95zai2m6sg2gpul94.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbe95zai2m6sg2gpul94.jpg" alt="MCP Client" width="800" height="781"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP Servers – Lightweight servers that expose specific functionalities, serving as bridges between AI models and data sources.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;Data Flow in MCP&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pull Data → AI queries an MCP server for context (e.g., checking a user’s calendar).&lt;/li&gt;
&lt;li&gt;Trigger Actions → AI instructs an MCP server to take action (e.g., reschedule meetings, send emails).&lt;/li&gt;
&lt;li&gt;Persistent Connection → Unlike APIs that require repeated calls, MCP maintains continuous communication between AI and tools.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Implementing MCP with Spring AI
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Client Starters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;spring-ai-mcp-client-spring-boot-starter - Core starter providing STDIO and HTTP-based SSE support&lt;br&gt;
spring-ai-mcp-client-webflux-spring-boot-starter - WebFlux-based SSE transport implementation&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server Starters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;spring-ai-mcp-server-spring-boot-starter - Core server with STDIO transport support&lt;br&gt;
spring-ai-mcp-server-webmvc-spring-boot-starter - Spring MVC-based SSE transport implementation&lt;br&gt;
spring-ai-mcp-server-webflux-spring-boot-starter - WebFlux-based SSE transport implementation&lt;/p&gt;
&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Dependency&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.ai&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-ai-mcp-client-spring-boot-starter&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bean Setup&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Bean
    public ChatClient chatClient(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools) {
        return chatClientBuilder
                .defaultTools(tools)
                .build();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Config MCP Server File&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "mcpServers": {
    "slack": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "SLACK_BOT_TOKEN",
        "-e",
        "SLACK_TEAM_ID",
        "mcp/slack"
      ],
      "env": {
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add Specific function to be called by MCP Server in your prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    **4. Formatting for Slack:**
                           - Present the information in a structured and well-organized format
                           - Use **bold headings** (`*Decision and Recommendation*`)
                           - Post the summary to the **'#all-ai-agent-alerts'** Slack channel \t
                          \s
                        The summary should be concise, clear, and actionable to help the credit team quickly understand what decision we have to take.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Slack Setup
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/AVIMBU/slack-mcp-server" rel="noopener noreferrer"&gt;https://github.com/AVIMBU/slack-mcp-server&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.anthropic.com/news/model-context-protocol" rel="noopener noreferrer"&gt;MCP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/modelcontextprotocol" rel="noopener noreferrer"&gt;MCP Github Project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>mcp</category>
      <category>spring</category>
      <category>ai</category>
    </item>
    <item>
      <title>Ai Agent Patterns with Spring AI</title>
      <dc:creator>lucasnscr</dc:creator>
      <pubDate>Mon, 24 Feb 2025 00:22:46 +0000</pubDate>
      <link>https://dev.to/lucasnscr/ai-agent-patterns-with-spring-ai-43gl</link>
      <guid>https://dev.to/lucasnscr/ai-agent-patterns-with-spring-ai-43gl</guid>
      <description>&lt;h1&gt;
  
  
  AI Agents and Their Patterns: A Practical Perspective
&lt;/h1&gt;

&lt;p&gt;As AI-driven applications evolve, developers are increasingly leveraging large language model (LLM) agents to execute complex tasks efficiently. However, the most effective implementations rely not on overly complex frameworks but on simple, composable design patterns.&lt;/p&gt;

&lt;p&gt;This article explores the distinction between workflows and agents, identifies key patterns used in AI-driven systems, and examines how these concepts apply to a Spring AI implementation designed for intelligent news retrieval based on user preferences.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are AI Agents?
&lt;/h2&gt;

&lt;p&gt;AI agents are systems that use LLMs to process information, interact with tools, and perform actions. They can be classified into two broad categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Workflows: Structured sequences where LLMs and external tools follow predefined execution paths. These systems prioritize predictability and are ideal for well-defined, repeatable tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agents: More dynamic and autonomous systems where LLMs dictate their own processes, selecting tools and determining how to accomplish tasks. This allows for greater flexibility and adaptation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choosing between these approaches depends on the problem domain—workflows excel in structured automation, while agents are preferable when decisions need to be made dynamically at scale.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Key Patterns in AI Agent Systems
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Chain Workflow&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A Chain Workflow organizes multiple steps in a linear sequence, where the output of one step feeds into the next. It ensures clarity and control while allowing for slight adaptability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tasks with clear sequential steps&lt;/li&gt;
&lt;li&gt;When you want to trade latency for higher accuracy&lt;/li&gt;
&lt;li&gt;When each step builds on the previous step's output&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Parallelization Workflow&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This pattern involves executing multiple tasks simultaneously, increasing efficiency in data-intensive operations. It is useful when fetching or processing large amounts of information concurrently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Processing large volumes of similar but independent items&lt;/li&gt;
&lt;li&gt;Tasks requiring multiple independent perspectives&lt;/li&gt;
&lt;li&gt;When processing time is critical and tasks are parallelizable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffebbnyphui29v8vv2r22.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffebbnyphui29v8vv2r22.jpeg" alt="Parallelization Workflow" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Routing Workflow&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A Routing Workflow dynamically directs execution paths based on input conditions, allowing the system to adapt to different cases without predefined sequences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex tasks with distinct categories of input&lt;/li&gt;
&lt;li&gt;When different inputs require specialized processing&lt;/li&gt;
&lt;li&gt;When classification can be handled accurately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklmzl6w50pr5f6egfb26.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklmzl6w50pr5f6egfb26.jpeg" alt="Routing workflow" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Orchestrator-Workers&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Orchestrator AI delegates tasks to multiple specialized worker agents, each responsible for a distinct function (e.g., data retrieval, analysis, summarization).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex tasks where subtasks can't be predicted upfront&lt;/li&gt;
&lt;li&gt;Tasks requiring different approaches or perspectives&lt;/li&gt;
&lt;li&gt;Situations needing adaptive problem-solving&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxvz9eqf9jw7pz3ovkin.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxvz9eqf9jw7pz3ovkin.jpeg" alt="Orchestrator-Workers Workflow" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Evaluator-Optimizer&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This pattern involves an Evaluator assessing the quality of an agent’s output and an Optimizer refining future responses based on feedback, improving accuracy over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear evaluation criteria exist&lt;/li&gt;
&lt;li&gt;Iterative refinement provides measurable value&lt;/li&gt;
&lt;li&gt;Tasks benefit from multiple rounds of critique&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fng7tdgvzvk1ci522dytf.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fng7tdgvzvk1ci522dytf.jpeg" alt="Evaluator-Optimizer Workflow" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Agent Patterns Used
&lt;/h2&gt;

&lt;p&gt;Patterns were used in the project:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Chain Workflow&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Description&lt;/strong&gt;: Chaining prompts or tasks to improve accuracy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application in the Project&lt;/strong&gt;: The workflow involves retrieving user preferences and then fetching and analyzing news based on those preferences. This can be seen as a chain of tasks, where the output of one task (user preferences) is used as input for the next (news retrieval).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Routing Workflow&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Description&lt;/strong&gt;: Intelligent routing of inputs to specialized flows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application in the Project&lt;/strong&gt;: The &lt;code&gt;GetNewsByUserPreferences&lt;/code&gt; service routes the request to different API endpoints (crypto or stocks) based on the user's topic of interest. This is an example of &lt;strong&gt;Routing Workflow&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Orchestrator-Workers&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Description&lt;/strong&gt;: A central AI (orchestrator) distributes tasks to specialized subprocesses (workers).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application in the Project&lt;/strong&gt;: The &lt;code&gt;NewsService&lt;/code&gt; acts as an orchestrator, coordinating news retrieval and analysis with the AI model. The AI model (OpenAiChatModel) functions as a specialized worker for text analysis.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Evaluator-Optimizer&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Description&lt;/strong&gt;: Use of LLMs for iterative evaluation and refinement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application in the Project&lt;/strong&gt;: The &lt;code&gt;extractNewsAndGiveOpinion&lt;/code&gt; method uses an AI model to summarize and analyze news, which can be seen as a form of content evaluation and refinement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Spring Ai and Tool Calling
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Spring AI&lt;/strong&gt; is a framework that facilitates the integration of AI functionalities into Spring applications. One of its key features is &lt;strong&gt;Tool Calling&lt;/strong&gt;, which allows AI models to interact with external APIs (tools) to extend their capabilities. These tools can be used for:&lt;/p&gt;

&lt;p&gt;Details the implementation of &lt;a href="https://docs.spring.io/spring-ai/reference/api/tools.html" rel="noopener noreferrer"&gt;Tool Calling&lt;/a&gt; in Spring AI, focusing on the creation of AI agents that use tools to retrieve information and perform actions. Additionally, we evaluate whether some of the common workflow patterns in AI systems were used, such as &lt;strong&gt;Chain Workflow&lt;/strong&gt;, &lt;strong&gt;Parallelization Workflow&lt;/strong&gt;, &lt;strong&gt;Routing Workflow&lt;/strong&gt;, &lt;strong&gt;Orchestrator-Workers&lt;/strong&gt;, and &lt;strong&gt;Evaluator-Optimizer&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;UserPreferencesService&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This service is responsible for retrieving user preferences from a repository (e.g., a database). It is implemented as a function (&lt;code&gt;Function&amp;lt;UserPreferenceRequest, UserPreferenceResponse&amp;gt;&lt;/code&gt;) and exposed as a Spring bean.&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="nd"&gt;@Bean&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="no"&gt;GET_USER_PREFERENCES_FUNCTION_NAME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Description&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Get topic by userId"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserPreferenceRequest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;UserPreferenceResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getUserPreferencesInfo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;UserPreferencesRepository&lt;/span&gt; &lt;span class="n"&gt;userPreferencesRepository&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UserPreferencesService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userPreferencesRepository&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;h4&gt;
  
  
  Features:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Takes a &lt;code&gt;userId&lt;/code&gt; as input.&lt;/li&gt;
&lt;li&gt;Queries the repository to retrieve user preferences.&lt;/li&gt;
&lt;li&gt;Returns the user's topic of interest (e.g., "crypto" or "stocks").&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. &lt;strong&gt;GetNewsByUserPreferences&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This service retrieves news based on the user's topic of interest and analyzes them using an AI model. It is also implemented as a function (&lt;code&gt;Function&amp;lt;GetNewsByPreferenceRequest, GetNewsByPreferenceResponse&amp;gt;&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="nd"&gt;@Bean&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="no"&gt;GET_LATEST_NEWS_BY_TOPIC_FUNCTION_NAME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Description&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Get latest news from user topic"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GetNewsByPreferenceRequest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;GetNewsByPreferenceResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getNewsFromPreference&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NewsService&lt;/span&gt; &lt;span class="n"&gt;newsService&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GetNewsByUserPreferences&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newsService&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;h4&gt;
  
  
  Features:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Takes a topic of interest (e.g., "crypto" or "stocks") as input.&lt;/li&gt;
&lt;li&gt;Queries an external service (e.g., AlphaClientNewsSentimentals) to retrieve related news.&lt;/li&gt;
&lt;li&gt;Uses an AI model (e.g., OpenAI) to summarize and analyze the news.&lt;/li&gt;
&lt;li&gt;Returns the summarized and analyzed news.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. &lt;strong&gt;NewsService&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This service is responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieving news from an external API (AlphaClientNewsSentimentals).&lt;/li&gt;
&lt;li&gt;Using an AI model (OpenAiChatModel) to summarize and analyze the news.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&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;NewsService&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;final&lt;/span&gt; &lt;span class="nc"&gt;AlphaClientNewsSentimentals&lt;/span&gt; &lt;span class="n"&gt;alphaClient&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;final&lt;/span&gt; &lt;span class="nc"&gt;OpenAiChatModel&lt;/span&gt; &lt;span class="n"&gt;chatModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;NewsService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AlphaClientNewsSentimentals&lt;/span&gt; &lt;span class="n"&gt;alphaClient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;OpenAiChatModel&lt;/span&gt; &lt;span class="n"&gt;chatModel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;alphaClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;alphaClient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chatModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chatModel&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="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NewsAndSentimentals&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getNews&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GetNewsRequest&lt;/span&gt; &lt;span class="n"&gt;request&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="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;category&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="s"&gt;"crypto"&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="n"&gt;alphaClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requestCrypto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CryptoEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BITCOIN&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTicker&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;alphaClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requestStock&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StockEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;APPLE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTicker&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;public&lt;/span&gt; &lt;span class="nc"&gt;GetNewsByPreferenceResponse&lt;/span&gt; &lt;span class="nf"&gt;extractNewsAndGiveOpinion&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;NewsAndSentimentals&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;newsResponses&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="nc"&gt;ChatClient&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="n"&gt;chatModel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;system&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&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;"You are a professional financial analyst..."&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;u&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;"{news}"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;param&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"news"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newsResponses&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GetNewsByPreferenceResponse&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="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Next Steps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Implement &lt;strong&gt;Parallelization Workflow&lt;/strong&gt; to improve efficiency in news retrieval.&lt;/li&gt;
&lt;li&gt;Explore the use of &lt;strong&gt;Evaluator-Optimizer&lt;/strong&gt; for iterative refinement of the analyses generated by the AI model.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How to Run the Project
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 17+&lt;/li&gt;
&lt;li&gt;Spring Boot 3.x&lt;/li&gt;
&lt;li&gt;OpenAI API Key (for the AI model)&lt;/li&gt;
&lt;li&gt;Configuration of the user preferences repository (e.g., a database).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Setup&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the OpenAI API Key in &lt;code&gt;application.properties&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt; &lt;span class="py"&gt;spring.ai.openai.api-key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;YOUR_KEY_HERE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Add the Alpha Advantage API Key in &lt;code&gt;application.properties&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt; &lt;span class="py"&gt;Alpha.api-key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;=YOUR_KEY_HERE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;Running the Sql's: Schema and data&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Execution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run the project with:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; ./mvnw spring-boot:run
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Testing&lt;/strong&gt;:&lt;/p&gt;
&lt;h2&gt;
  
  
  - Use REST endpoints to test preference and news retrieval.
&lt;/h2&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/lucasnscr/Ai-Function-SpringAi" rel="noopener noreferrer"&gt;Github Repositoru&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Applying GenAI Design Patterns to Build a Next-Generation Financial Analysis Application</title>
      <dc:creator>lucasnscr</dc:creator>
      <pubDate>Sun, 09 Feb 2025 19:09:36 +0000</pubDate>
      <link>https://dev.to/lucasnscr/applying-genai-design-patterns-to-build-a-next-generation-financial-analysis-application-551k</link>
      <guid>https://dev.to/lucasnscr/applying-genai-design-patterns-to-build-a-next-generation-financial-analysis-application-551k</guid>
      <description>&lt;p&gt;Generative AI (GenAI) is transforming industries by enabling machines to create human-like content across text, images, and beyond. This revolutionary technology is not only powering innovative applications in creative fields but is also making significant inroads into domains such as finance, healthcare, and customer service. With GenAI, organizations can harness advanced models that generate context-rich outputs, augment traditional data retrieval methods, and deliver personalized insights, fundamentally reshaping how we interact with information and make decisions.&lt;/p&gt;

&lt;p&gt;Relying on substandard or poorly curated datasets to train LLMs poses significant risks. Without a solid foundation of accurate, representative data, these models may produce outputs that are both factually incorrect and misleading—a phenomenon known as hallucinations. Hallucinations occur when the model invents details or delivers confidently erroneous information that isn’t grounded in its training data. Such inaccuracies can drive poor decision-making, particularly in high-stakes fields like finance, healthcare, or legal services, where precision and trust are critical. Therefore, maintaining dataset integrity is essential for mitigating these risks and building reliable AI systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mitigating Risks with GenAI Patterns: Leveraging Embeddings, RAG, and Query Transformation to Prevent Hallucinations and Ensure Reliable Outputs
&lt;/h2&gt;

&lt;p&gt;Mitigating risks in GenAI systems is achievable by leveraging key design patterns that address the inherent challenges of training on unreliable data. By utilizing &lt;strong&gt;Embedding Generation&lt;/strong&gt;, raw financial text is transformed into meaningful vector representations, ensuring that the semantic nuances of the data are captured accurately. In parallel, &lt;strong&gt;Retrieval Augmented Generation (RAG)&lt;/strong&gt; enriches LLM prompts with context retrieved from a vector store, thereby bridging the gap in static knowledge bases and reducing the likelihood of hallucinations. Additionally, &lt;strong&gt;Query Transformation&lt;/strong&gt; refines user queries to align seamlessly with the underlying document embeddings, enhancing the retrieval of relevant information. Together, these patterns work synergistically to prevent the generation of misleading outputs and to ensure the delivery of reliable, context-aware responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Embeddings: From Raw Data to Meaningful Vectors
&lt;/h3&gt;

&lt;p&gt;One of the foundational patterns discussed by &lt;a href="https://martinfowler.com/articles/gen-ai-patterns/#embedding" rel="noopener noreferrer"&gt;Fowler&lt;/a&gt; is the use of embeddings. In his article, he explains that embeddings transform large data blocks (whether text or images) into numeric vectors in a high-dimensional space so that items with similar semantic meaning end up near each other. In our application, this concept is critical for enabling similarity search across financial documents and news.&lt;/p&gt;

&lt;h4&gt;
  
  
  Embeddings implementation with SpringAI
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Tokenization &amp;amp; Splitting&lt;/strong&gt;&lt;br&gt;
The saveVectorDb method begins by using a TokenTextSplitter to break down a list of content strings into smaller chunks, converting each into a Document instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List&amp;lt;Document&amp;gt; documentList = textSplitter.apply(   contentList.stream().map(Document::new).collect(Collectors.toList());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This aligns with the idea of chunking large documents into manageable pieces—a common practice to preserve contextual details in embeddings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Embedding Generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For each document, the method calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;embeddingModel.embed(document);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This invocation transforms the document text into an embedding vector. The vector is then stored in the vector store for later similarity searches. This step reflects the core purpose of embeddings in our GenAI architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Metadata Association&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Beyond generating embeddings, the method attaches additional metadata:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.getMetadata().put("metadata", metadata);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of redundantly storing the embedding in the metadata, this field is used to store auxiliary information (such as document type or indexing timestamp) that can be used to filter or display results later. Fowler’s discussion on structuring the knowledge base stresses the importance of separating data (embeddings) from contextual information (metadata).&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieval Augmented Generation (RAG): Enriching Prompts with Relevant Context
&lt;/h3&gt;

&lt;p&gt;Martin Fowler’s &lt;a href="https://martinfowler.com/articles/gen-ai-patterns/#embedding" rel="noopener noreferrer"&gt;article&lt;/a&gt; describes RAG as a way to overcome the limitations of LLMs by augmenting user prompts with relevant document fragments retrieved from an external knowledge base. This approach helps the LLM produce answers that are factually grounded and contextually appropriate.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementing RAG with SpringAI
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Constructing an Advised Request&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The method retrieveRelevantDocuments builds an AdvisedRequest using the user query and a configured chat model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AdvisedRequest request = AdvisedRequest.builder()
        .chatModel(chatModel)
        .userText(query)
        .build();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This request serves as the input for the retrieval augmentation process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using the RetrievalAugmentationAdvisor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The request is then passed to the advisor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AdvisedRequest advisedRequest = retrievalAugmentationAdvisor.before(request);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood, this advisor orchestrates a series of operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query Transformation:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The advisor uses a RewriteQueryTransformer (created in the private method createQueryTransformers()) to refine or rephrase the query. This transformation is crucial for overcoming the “minimalistic user query” problem discussed by Fowler.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Document Retrieval:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A VectorStoreDocumentRetriever (built in createDocumentRetriever()) searches the vector store using the refined query’s embedding. It applies a similarity threshold (set to 0.65 in our implementation) and limits the number of retrieved documents to the top 5.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query Augmentation:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, a ContextualQueryAugmenter (from createQueryAugmenter()) supplements the original query with the context retrieved from the vector store. In our implementation, the augmenter is configured with allowEmptyContext(true), meaning that even if no documents are deemed sufficiently similar, the original query is preserved instead of being overridden by a fallback message.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extracting the Retrieved Documents:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After the advisor has processed the request, the method extracts the retrieved documents from the context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Object contextValue = advisedRequest.adviseContext().get(RetrievalAugmentationAdvisor.DOCUMENT_CONTEXT);
if (contextValue instanceof List&amp;lt;?&amp;gt; documents) {
    return (List&amp;lt;Document&amp;gt;) documents;
}
return List.of();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This final step directly implements the RAG pattern: enriching the query with retrieved context before passing it on to the LLM for answer generation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Hybrid Retriever and Query Transformation: Enhancing Search Efficiency
&lt;/h4&gt;

&lt;p&gt;Fowler’s discussion on the Hybrid Retriever pattern emphasizes that while dense embeddings are powerful, they can be complemented by traditional keyword or BM25 searches to overcome their limitations. Although our implementation in AIFinancialRepository currently focuses on vector-based retrieval, the integration of a query transformer shows an appreciation for combining multiple retrieval strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query Transformer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The private method createQueryTransformers() builds a RewriteQueryTransformer using a ChatClient. This transformer adapts user queries to better match the representation of the documents in the vector store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private QueryTransformer createQueryTransformers() {
    ChatClient chatClient = ChatClient.builder(chatModel).build();
    return RewriteQueryTransformer.builder()
            .chatClientBuilder(chatClient.mutate())
            .build();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By rewriting the query, the system addresses ambiguities and refines the search input, increasing the chances of retrieving relevant documents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VectorStoreDocumentRetriever&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The method createDocumentRetriever() constructs a document retriever that searches the vector store using similarity thresholds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private VectorStoreDocumentRetriever createDocumentRetriever() {
    return VectorStoreDocumentRetriever.builder()
            .vectorStore(vectorStore)
            .similarityThreshold(0.65)
            .topK(5)
            .build();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This component implements the core of the hybrid retrieval strategy by ensuring that only the most semantically similar document fragments are returned.&lt;/p&gt;

&lt;h1&gt;
  
  
  AI Financial Analyst Design System
&lt;/h1&gt;

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

&lt;h1&gt;
  
  
  Comparative Analysis of AI Financial Analyst Implementations
&lt;/h1&gt;

&lt;p&gt;In our journey to develop a robust AI Financial Analyst, we experimented with two distinct implementations that leverage different generative AI models and embedding algorithms. This section compares these two approaches in light of Martin Fowler’s GenAI patterns and our architectural goals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Version 1: OpenAI’s GPT4o with text-embedding-ada-002
&lt;/h2&gt;

&lt;p&gt;The first version of our application was built around &lt;strong&gt;OpenAI’s&lt;/strong&gt; &lt;strong&gt;GPT4o&lt;/strong&gt; model—a general-purpose large language model designed for a wide range of natural language tasks. GPT4o excels in generating coherent, contextually rich responses across various domains. Its strength lies in its versatility and the ability to handle diverse queries, making it a strong candidate for customer-facing applications where broad knowledge and adaptability are critical.&lt;/p&gt;

&lt;p&gt;To complement GPT4o, we employed OpenAI’s &lt;strong&gt;text-embedding-ada-002&lt;/strong&gt; algorithm for generating embeddings. This algorithm transforms raw financial text into dense, high-dimensional vectors that capture semantic meaning. Text-embedding-ada-002 is known for its cost efficiency, robust performance, and general applicability across tasks such as similarity search, clustering, and semantic comparison. However, while it performs admirably in generating embeddings for general-purpose retrieval, its design is not explicitly optimized for deep reasoning or domain-specific nuances.&lt;/p&gt;

&lt;h2&gt;
  
  
  Version 2: DeepSeek R1 with nomic-embed-text on Ollama
&lt;/h2&gt;

&lt;p&gt;The second implementation pivots to a locally hosted solution using &lt;strong&gt;DeepSeek R1&lt;/strong&gt; a model tailored for enhanced reasoning capabilities. Running on the Ollama platform, DeepSeek R1 was selected for scenarios where precise, domain-specific reasoning is paramount, such as detailed financial analysis. Unlike the more general-purpose GPT4o, DeepSeek R1 is &lt;strong&gt;fine-tuned&lt;/strong&gt; to process complex queries and provide reasoned responses that align closely with the intricate requirements of financial analytics.&lt;/p&gt;

&lt;p&gt;For embedding generation in this version, we use the &lt;strong&gt;nomic-embed-text&lt;/strong&gt; algorithm. This embedding algorithm is designed to complement the reasoning strengths of DeepSeek R1, focusing on extracting the nuanced relationships within financial texts. While text-embedding-ada-002 offers broad semantic representation, nomic-embed-text is optimized for scenarios where contextual reasoning is essential, ensuring that the resultant embeddings preserve subtle semantic details crucial for informed decision-making.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Benchmark Summary:&lt;/strong&gt;
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Generality vs. Specialization&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GPT4o is a general-purpose model suited for a wide array of tasks, making it versatile for various applications. In contrast, DeepSeek R1 is specialized for reasoning, offering enhanced performance in scenarios that demand a higher level of analytical depth.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Embedding Algorithms&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Text-embedding-ada-002 provides robust and cost-effective embeddings that work well for generic semantic similarity tasks. On the other hand, nomic-embed-text is tailored to support DeepSeek R1’s reasoning abilities, potentially offering richer representations in context-specific financial analysis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.nomic.ai/blog/posts/nomic-embed-text-v1" rel="noopener noreferrer"&gt;Nomic AI Doc&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Deployment Considerations&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The GPT4o-based implementation leverages cloud-based, managed services from OpenAI, which can simplify scaling and maintenance. The DeepSeek R1 solution, running locally via Ollama, offers greater control over data and model tuning, which is beneficial for organizations that require enhanced privacy or need to fine-tune the model for domain-specific tasks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Database Setup&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both implementations leverage PGVector as the underlying vector database but differ in key configuration parameters that directly impact the effectiveness of the retrieval process.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Distance Type (COSINE_DISTANCE)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setting indicates that the similarity between vectors is measured using cosine distance, which evaluates the cosine of the angle between two vectors. It is a widely used metric in embedding spaces because it emphasizes the directional similarity rather than the magnitude of the vectors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Index Type (HNSW)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Hierarchical Navigable Small World (HNSW) algorithm is employed for indexing. HNSW is an approximate nearest neighbor search method optimized for high-dimensional spaces. It provides fast and scalable retrieval, making it ideal for applications that require efficient similarity search among thousands or millions of vectors.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dimensions&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A crucial difference between the two versions is the dimensionality of the embeddings.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The DeepSeek R1 implementation uses .dimensions(1024), reflecting that the nomic-embed-text embedding algorithm produces 1024-dimensional vectors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In contrast, the GPT4o implementation uses .dimensions(1536), as the text-embedding-ada-002 algorithm generates higher-dimensional (1536) embeddings.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This difference affects the granularity and capacity of the embeddings to capture semantic nuances, with the higher dimension potentially encoding more detail but also demanding stricter similarity criteria.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Similarity Threshold&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The document retriever’s configuration also varies between the two implementations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For DeepSeek R1, the similarity threshold is set at .similarityThreshold(0.65), which allows documents with a cosine similarity above 0.65 to be considered relevant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For GPT4o, the threshold is higher at .similarityThreshold(0.82), demanding a closer match between the query embedding and stored document embeddings.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This stricter threshold in GPT4o likely compensates for the richer, more detailed 1536-dimensional embeddings, ensuring that only highly relevant documents are retrieved.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Output Results&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After we did the ingestion data related News and Sentimentals about bitcoin we did this question.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "question": "What the sentiment and price expectations for Bitcoin in the next days. Make a deep analysis."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response for GPT4o&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Analysis Type: Market Trend and Sentiment Analysis for Bitcoin

Key Metric/Insight: The primary focus is on Bitcoin's price movement, trading volume, and market sentiment indicators. Key metrics include recent price changes, trading volume fluctuations, and sentiment scores derived from social media and news sources.

Source &amp;amp; Reliability: Data is sourced from cryptocurrency exchanges for price and volume, and sentiment data is aggregated from social media platforms and news articles. The reliability of price and volume data is high due to real-time updates, while sentiment data is moderately reliable, subject to rapid changes in public opinion.

Reasoning/Impact: Bitcoin's price is highly sensitive to market sentiment, which can drive significant volatility. Positive sentiment often leads to increased buying pressure, potentially driving prices up, while negative sentiment can result in selling pressure and price declines. Understanding sentiment helps anticipate short-term price movements.

Data Comparisons: Recent data shows Bitcoin's price has been fluctuating within a specific range, with a slight upward trend over the past week. Trading volume has been consistent, indicating steady interest. Sentiment analysis reveals a neutral to slightly positive sentiment, with increased mentions of Bitcoin in the context of potential regulatory developments.

Historical Context/Comparative Insight: Historically, Bitcoin's price tends to experience increased volatility during periods of heightened regulatory discussions or macroeconomic changes. Comparatively, the current sentiment is more positive than during previous regulatory scares, suggesting a potential for price stability or moderate growth.

Final Opinion: Based on the current metrics and sentiment analysis, the short-term outlook for Bitcoin appears cautiously optimistic. If sentiment remains stable or improves, there is potential for a modest price increase. However, investors should remain vigilant for any sudden changes in sentiment or regulatory news. Recommendation: Hold, with a watchful eye on sentiment shifts and regulatory announcements.

Data Patterns &amp;amp; Observations: A recurring pattern is the correlation between sentiment spikes and short-term price movements. Positive news or sentiment often precedes price increases, while negative sentiment can lead to declines. Monitoring sentiment trends can provide early indicators of potential price changes.

Additional Considerations: Keep an eye on liquidity metrics, as they can impact price volatility. Additionally, consider macroeconomic factors such as interest rates and inflation, which can influence investor behavior in the cryptocurrency market.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response for Deepseek R1&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Everything inside  was how Deepseek build reasoning the answer:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;think&amp;gt;
Alright, so I need to figure out how to analyze Bitcoin's sentiment and price expectations for the next few days. Hmm, where do I start? Well, first off, I know that Bitcoin's price is influenced by various factors like market trends, news, regulations, and even macroeconomic indicators. But since the question is about sentiment and price expectations in the next day or two, maybe looking at technical analysis would be helpful.

I remember hearing about things like moving averages, RSI (Relative Strength Index), and Volume as part of technical indicators. If Bitcoin's price crosses above a significant moving average, that might indicate positive sentiment because it could signal strength in the market. Conversely, failing to do so might mean negative sentiment.

RSI is another one I'm somewhat familiar with. It measures how overbought or oversold an asset is. An RSI below 30 usually suggests buying pressure, while above 70 indicates selling pressure. If Bitcoin's RSI is rising, that could be a good sign for price movement in the coming days.

Volume also plays a role. High trading volume can indicate strong interest and confidence in the market. If Bitcoin sees a surge in volume alongside positive indicators like moving averages or buying signals, it might signal bullish momentum.

I should consider looking at historical data too—maybe see how Bitcoin's price has moved when these indicators were signaling positive or negative trends. This could give me some patterns to predict future movements.

Wait, but sentiment analysis can also involve news events. Recent major news about regulations in countries like the U.S. or Europe regarding Bitcoin could impact its price and sentiment. If there are upcoming significant events, that's something I should monitor.

I'm a bit unsure about how reliable these indicators are on their own. Sometimes technical indicators can give false signals, so relying solely on them might not be enough. Maybe combining them with other factors like market news or geopolitical events would provide a more accurate picture.

Also, the behavioral aspect—how retail investors behave in the markets—could influence short-term price movements. If there's a lot of buying activity due to fear or excitement, it could drive prices up or down regardless of technical signals.

Looking at specific timeframes might help too. For instance, if Bitcoin shows bullish patterns during certain times of the day, that could predict its behavior in the coming hours.

I think I need to check some sources for reliable data—maybe websites like CoinMarketCap, CoinDesk, or financial news sites that track Bitcoin trends. Also, looking into Twitter sentiment for retail investors might provide real-time insights on market-moving news.

Wait, but sentiment analysis can be subjective. How do you quantify something as intangible as market sentiment? Maybe using sentiment scores from social media posts or news articles could give a gauge of overall feelings towards Bitcoin in the market.

I should also consider the correlation between Bitcoin's price and other assets like Ethereum or traditional cryptocurrencies such as gold, silver, or Bitcoin itself through time-series analysis. This might help identify if there are any patterns or dependencies that can predict future moves.

Another point is to look at the correlation with macroeconomic indicators—like inflation rates or interest rates—if they have an impact on Bitcoin's price due to its status as a hedge against inflation.

But I'm not entirely sure how all these pieces fit together. Maybe starting with a simple moving average analysis would be a good first step, then incorporating RSI and volume data for more depth. Combining that with recent news or geopolitical developments could provide a comprehensive outlook.

I think I'll outline the steps: First, check Bitcoin's current price and key technical indicators like MA (moving averages), RSI, and volume. Then, look at any upcoming significant events that might affect its market. Analyze how sentiment is shaping up on social media or news feeds. Finally, see if there are patterns in historical data correlating these factors with future price movements.

So, putting it all together, I can predict whether Bitcoin's price is expected to go up or down based on the combination of these indicators and current market sentiments.
&amp;lt;/think&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Answer:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**Bitcoin Sentiment and Price Expectations Analysis (Next 7 Days)**

**1. Technical Indicators:**
   - **Moving Averages:** Bitcoin has recently crossed above a significant moving average, indicating bullish sentiment due to potential strength in market sentiment.
   - **RSI (Relative Strength Index):** The RSI is currently below 30, signaling buying pressure and positive sentiment among investors.
   - **Volume:** High trading volume indicates strong market interest and confidence, supporting the bullish trend.

**2. News and Events:**
   - Monitor recent news from major countries like the U.S., U.K., and European Union regarding Bitcoin regulations, as these could impact sentiment and price movements.

**3. Behavioral Analysis:**
   - Consider retail investor behavior—patterns of buying during specific times of the day that might influence short-term price actions.

**4. Sentiment Sources:**
   - Analyze social media sentiment, particularly from platforms like Twitter where retail investors often share market-moving news.

**5. Correlation with Other Assets and Indicators:**
   - Examine correlations between Bitcoin's price and other assets (Ethereum, gold) or macroeconomic indicators (inflation rates) for potential predictive patterns.

**6. Historical Context:**
   - Review historical data to identify patterns where these indicators coincided with future price movements, enhancing the reliability of predictions.

**Conclusion:**
Combining these factors—positive technical signals, bullish sentiment, and supportive news—it is recommended that Bitcoin's price may experience an upward trend in the next 7 days. However, this analysis should be closely monitored as market dynamics can change rapidly due to external shocks or shifts in investor behavior.

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Consideration
&lt;/h2&gt;

&lt;p&gt;After gathering responses from each AI system, I posed the same question to OpenAI O3-mini, DeepSeek R1, and Gemini from Google. I selected the answer from OpenAI for the OpenAI O3-mini system, and for both DeepSeek R1 and Gemini, I opted for the DeepSeek response. In effect, this results in a 2-to-1 preference in favor of DeepSeek.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since the DeepSeek R1 model is running locally via Ollama, both the process of converting data into embedding vectors and the retrieval process experienced higher latency compared to cloud-based solutions like OpenAI’s GPT4o implementation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lucasnscr/ai-financial-analyst" rel="noopener noreferrer"&gt;AI Financial Analyst Repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.spring.io/spring-ai/reference/index.html" rel="noopener noreferrer"&gt;Spring AI Doc&lt;/a&gt;&lt;/p&gt;

</description>
      <category>spring</category>
      <category>genai</category>
      <category>deepseek</category>
      <category>chatgpt</category>
    </item>
    <item>
      <title>Multithreading and Patterns</title>
      <dc:creator>lucasnscr</dc:creator>
      <pubDate>Mon, 05 Aug 2024 12:24:44 +0000</pubDate>
      <link>https://dev.to/lucasnscr/multithreading-and-patterns-4nmk</link>
      <guid>https://dev.to/lucasnscr/multithreading-and-patterns-4nmk</guid>
      <description>&lt;h1&gt;
  
  
  Multithreading-Design-Patterns
&lt;/h1&gt;

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

&lt;p&gt;Implementing the most used multithreading design patterns with use cases and examples in real life scenarios using Java and Spring Boot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction to Multithreading in Java
&lt;/h3&gt;

&lt;p&gt;Multithreading is a pivotal concept in modern software development that allows for the concurrent execution of two or more threads, enabling efficient utilization of CPU resources and improving the performance of applications. In Java, multithreading is a fundamental feature of the language, designed to enhance the responsiveness and throughput of applications by performing multiple tasks simultaneously within a single program.&lt;/p&gt;

&lt;p&gt;Java's robust support for multithreading is built into its core, providing developers with powerful tools to create and manage threads effortlessly. The &lt;code&gt;java.lang.Thread&lt;/code&gt; class and the &lt;code&gt;java.util.concurrent&lt;/code&gt; package form the backbone of Java's multithreading capabilities, offering a variety of classes and interfaces for thread manipulation, synchronization, and communication.&lt;/p&gt;

&lt;p&gt;At its essence, multithreading in Java involves dividing a program into smaller units of work, known as threads, which can run independently and concurrently. This approach not only maximizes the use of available CPU cores but also allows for more responsive and interactive applications, as time-consuming tasks like I/O operations or complex calculations can be performed in the background without freezing the main application thread.&lt;/p&gt;

&lt;p&gt;One of the key advantages of multithreading is the ability to design applications that remain responsive under heavy load. For instance, in a graphical user interface (GUI) application, multithreading can ensure that the user interface remains responsive while background tasks, such as data processing or network communication, are handled concurrently.&lt;/p&gt;

&lt;p&gt;However, developing multithreaded applications comes with its own set of challenges, such as thread synchronization, deadlocks, and race conditions. Java addresses these issues by providing synchronized methods and blocks, the &lt;code&gt;volatile&lt;/code&gt; keyword, and various concurrency utilities like locks, semaphores, and executors, which help in managing the complexities associated with multithreading.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing Multithreading Design Patterns in Spring Boot
&lt;/h3&gt;

&lt;p&gt;In this project, we will implement the following multithreading design patterns using Java and Spring Boot:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/lucasnscr/Multithreading-Design-Patterns/tree/main/active-object-pattern" rel="noopener noreferrer"&gt;Active Object Pattern&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/lucasnscr/Multithreading-Design-Patterns/tree/main/barrier-pattern" rel="noopener noreferrer"&gt;Barrier Pattern&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/lucasnscr/Multithreading-Design-Patterns/tree/main/future-promises-pattern" rel="noopener noreferrer"&gt;Future Promises Pattern&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/lucasnscr/Multithreading-Design-Patterns/tree/main/monitor-object-pattern" rel="noopener noreferrer"&gt;Monitor Object Pattern&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/lucasnscr/Multithreading-Design-Patterns/tree/main/producer-consumer-pattern" rel="noopener noreferrer"&gt;Producer-Consumer Pattern&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/lucasnscr/Multithreading-Design-Patterns/tree/main/ready-writer-pattern" rel="noopener noreferrer"&gt;Reader-Writer Pattern&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/lucasnscr/Multithreading-Design-Patterns/tree/main/thread-pool-pattern" rel="noopener noreferrer"&gt;Thread Pool Pattern&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each pattern will be explained in detail, including its use cases and real-life examples. The implementation will demonstrate how to effectively use these patterns to handle concurrent tasks, ensuring responsive and efficient applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Active Object Pattern&lt;/strong&gt;
&lt;/h2&gt;

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

&lt;h4&gt;
  
  
  Explanation
&lt;/h4&gt;

&lt;p&gt;The Active Object Pattern helps manage concurrency by separating method invocation from execution. In this Spring Boot application, we demonstrated how to implement this pattern to process tasks asynchronously, ensuring that the server remains responsive even when handling long-running tasks. This approach can be extended to more complex scenarios such as handling multiple types of tasks or integrating with other services.&lt;/p&gt;

&lt;p&gt;The Active Object Pattern decouples method execution from method invocation to enhance concurrency and simplify synchronized object behavior. It consists of the following key components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Proxy&lt;/strong&gt;: Provides an interface for clients to send requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method Request&lt;/strong&gt;: Defines a request as an object that implements a method to be executed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduler&lt;/strong&gt;: Responsible for queuing and executing Method Requests on a separate thread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Servant&lt;/strong&gt;: Implements the methods exposed by the Proxy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Activation Queue&lt;/strong&gt;: Holds the Method Requests until they are executed by the Scheduler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Future&lt;/strong&gt;: Represents the result of an asynchronous computation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Use Cases
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GUI Applications&lt;/strong&gt;: Ensuring that the UI remains responsive by handling time-consuming tasks asynchronously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-Time Systems&lt;/strong&gt;: Managing tasks in robotics or real-time monitoring systems where operations need to be queued and executed asynchronously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server Applications&lt;/strong&gt;: Handling multiple client requests simultaneously without blocking.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Real-Life Example
&lt;/h4&gt;

&lt;p&gt;Imagine a web server handling multiple client requests to fetch data from a database. Using the Active Object Pattern, each client request is processed asynchronously, improving throughput and ensuring that the server remains responsive.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Barrier Pattern&lt;/strong&gt;
&lt;/h3&gt;

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

&lt;h4&gt;
  
  
  Explanation
&lt;/h4&gt;

&lt;p&gt;The Barrier Object Pattern ensures synchronization of multiple threads at a predefined point, preventing any thread from proceeding until all have reached the barrier. This Spring Boot application demonstrates the pattern by simulating tasks executed by multiple threads, synchronizing at a barrier before proceeding. This approach is useful in scenarios requiring coordinated completion of parallel tasks, such as parallel computing, batch processing, and gaming.&lt;/p&gt;

&lt;p&gt;The Barrier Object Pattern is used to synchronize multiple threads at a predefined point, ensuring that no thread proceeds until all threads have reached this barrier. This pattern is useful in scenarios where a set of tasks must be completed before any further steps can be taken.&lt;/p&gt;

&lt;h4&gt;
  
  
  Use Cases
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Parallel Computing&lt;/strong&gt;: When dividing a large computational task into smaller sub-tasks, each sub-task must be completed before the results can be combined.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Batch Processing&lt;/strong&gt;: Ensuring all tasks in a batch are completed before moving to the next batch.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Gaming&lt;/strong&gt;: Synchronizing the state of multiple players before advancing to the next level or stage.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Real-Life Example
&lt;/h4&gt;

&lt;p&gt;In a multiplayer online game, all players must complete their turns before the game can proceed to the next round. The Barrier Object Pattern can ensure that all players reach the synchronization point (end of their turn) before the game advances.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Future Promises Pattern&lt;/strong&gt;
&lt;/h3&gt;

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

&lt;h4&gt;
  
  
  Explanation
&lt;/h4&gt;

&lt;p&gt;The Future Promise Pattern is used for handling asynchronous computations, allowing tasks to run in parallel without blocking the main thread. In this Spring Boot application, we demonstrated the pattern by simulating multiple asynchronous tasks and combining their results. This approach is useful in scenarios like asynchronous web requests, concurrent task execution, and long-running computations, ensuring non-blocking and efficient handling of tasks.&lt;/p&gt;

&lt;p&gt;The Future Promise Pattern is used for asynchronous programming to handle the result of a computation that may not be immediately available. It involves two main components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Future&lt;/strong&gt;: Represents the result of an asynchronous computation. It provides methods to check if the computation is complete, to wait for its completion, and to retrieve the result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Promise&lt;/strong&gt;: Represents a proxy for a value that is not yet known. It acts as a placeholder for the result and allows the computation to be done asynchronously.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Use Cases
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous Web Requests&lt;/strong&gt;: Making non-blocking HTTP requests where the response is processed once it becomes available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrent Task Execution&lt;/strong&gt;: Running multiple tasks in parallel and processing their results once all tasks are completed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-Running Computations&lt;/strong&gt;: Handling computations that take a long time to complete without blocking the main thread.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Real-Life Example
&lt;/h4&gt;

&lt;p&gt;In an e-commerce application, processing a large number of orders simultaneously without blocking the main thread. Each order is processed asynchronously, and once all orders are processed, the results are combined and sent to the user.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Monitor Object Pattern&lt;/strong&gt;
&lt;/h3&gt;

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

&lt;h4&gt;
  
  
  Explanation
&lt;/h4&gt;

&lt;p&gt;The Monitor Object Pattern is used to achieve mutual exclusion and synchronization in concurrent programming. This Spring Boot application demonstrates the pattern by simulating a print queue system where multiple print jobs are handled sequentially. This approach is useful in scenarios like resource management, producer-consumer problems, and thread-safe caching, ensuring thread-safe and synchronized access to shared resources.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Mutual Exclusion&lt;/strong&gt;: Ensures that only one thread can access the critical section of code at a time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Condition Variables&lt;/strong&gt;: Used to allow threads to wait for certain conditions to be met before continuing execution.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Use Cases
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Resource Management&lt;/strong&gt;: Ensuring that multiple threads can access a limited resource without conflict.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Producer-Consumer Problem&lt;/strong&gt;: Managing synchronization between producer and consumer threads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thread-Safe Caching&lt;/strong&gt;: Ensuring thread-safe access to a cache or shared resource.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Real-Life Example
&lt;/h4&gt;

&lt;p&gt;Consider a print queue system where multiple print jobs are submitted from different computers to a single printer. The Monitor Object Pattern can ensure that only one print job is processed by the printer at a time, while other jobs wait their turn.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Producer-Consumer Pattern&lt;/strong&gt;
&lt;/h3&gt;

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

&lt;h4&gt;
  
  
  Explanation
&lt;/h4&gt;

&lt;p&gt;The Producer-Consumer Pattern is used to manage concurrent access to a shared buffer by multiple producer and consumer threads. This Spring Boot application demonstrates the pattern by simulating an order processing system where multiple orders are produced and consumed. This approach is useful in scenarios like logging systems, web servers, and task queues, ensuring efficient and synchronized handling of tasks without data loss or corruption.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Concepts
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Producers&lt;/strong&gt;: Threads that create data and put it into the buffer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consumers&lt;/strong&gt;: Threads that take data from the buffer and process it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buffer&lt;/strong&gt;: A shared resource where produced data is stored before being consumed. This can be implemented as a queue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Synchronization&lt;/strong&gt;: Ensures that producers and consumers do not access the buffer concurrently in a way that leads to data corruption or loss.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Use Cases
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Logging Systems&lt;/strong&gt;: Log messages are produced by various parts of an application and consumed by a logging thread that writes them to a file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web Servers&lt;/strong&gt;: Handling incoming HTTP requests (produced by clients) and processing them (consumed by worker threads).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task Queues&lt;/strong&gt;: Tasks generated by one part of an application and processed by worker threads in the background.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Real-Life Example
&lt;/h4&gt;

&lt;p&gt;In a food ordering system, multiple customers (producers) place orders which are added to a queue. Chefs (consumers) take orders from the queue and prepare the food. The queue ensures that orders are handled in the order they are received, and no orders are lost or duplicated.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Reader-Writer Pattern&lt;/strong&gt;
&lt;/h3&gt;

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

&lt;h4&gt;
  
  
  Explanation
&lt;/h4&gt;

&lt;p&gt;The Reader-Writer Pattern is a synchronization pattern that allows multiple readers to read from a shared resource concurrently while ensuring exclusive access for writers. This Spring Boot application demonstrates the pattern by simulating a data store that supports concurrent reads and exclusive writes. This approach is useful in scenarios like database systems, caching, and file systems, where read operations are frequent, and write operations must be done safely.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Concepts
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Readers&lt;/strong&gt;: Threads that read data from the shared resource. Multiple readers can read concurrently as long as no writer is writing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Writers&lt;/strong&gt;: Threads that write data to the shared resource. Writers require exclusive access, meaning no other readers or writers can access the resource while a writer is writing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read-Write Lock&lt;/strong&gt;: A synchronization mechanism that allows concurrent read access or exclusive write access to a shared resource.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Use Cases
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Database Systems&lt;/strong&gt;: Allowing multiple clients to read data concurrently while ensuring that data modifications are done exclusively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching&lt;/strong&gt;: Ensuring that cached data can be read by multiple threads simultaneously while updates to the cache are done exclusively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File Systems&lt;/strong&gt;: Allowing multiple processes to read from a file while ensuring that write operations are exclusive.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Real-Life Example
&lt;/h4&gt;

&lt;p&gt;In a news website, multiple users can read articles concurrently, but when an article is updated, the update operation must be exclusive to avoid data corruption.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Thread Pool Pattern&lt;/strong&gt;
&lt;/h3&gt;

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

&lt;h4&gt;
  
  
  Explanation
&lt;/h4&gt;

&lt;p&gt;The Thread Pool Pattern is used to manage and reuse a pool of threads to perform tasks concurrently, improving performance and resource management. This Spring Boot application demonstrates the pattern by simulating the handling of multiple tasks using a thread pool. This approach is useful in scenarios like web servers, database connection pools, and background processing, ensuring efficient and scalable handling of concurrent tasks.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Concepts
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Thread Pool&lt;/strong&gt;: A collection of pre-initialized threads that stand by to perform tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task Queue&lt;/strong&gt;: A queue where tasks are submitted for execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Worker Threads&lt;/strong&gt;: Threads from the thread pool that pick up tasks from the task queue and execute them.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Use Cases
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Web Servers&lt;/strong&gt;: Handling multiple incoming HTTP requests concurrently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database Connection Pools&lt;/strong&gt;: Managing a pool of database connections for efficient reuse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Background Processing&lt;/strong&gt;: Performing background tasks such as logging, data processing, etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Real-Life Example
&lt;/h4&gt;

&lt;p&gt;A web server handles multiple incoming HTTP requests. Instead of creating a new thread for each request, the server uses a thread pool to handle the requests concurrently, ensuring efficient resource usage and reducing the overhead of thread management.&lt;/p&gt;

</description>
      <category>java</category>
      <category>programming</category>
      <category>cloud</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Vector Database and Spring IA</title>
      <dc:creator>lucasnscr</dc:creator>
      <pubDate>Sun, 11 Feb 2024 21:11:24 +0000</pubDate>
      <link>https://dev.to/lucasnscr/vector-database-and-spring-ia-4dll</link>
      <guid>https://dev.to/lucasnscr/vector-database-and-spring-ia-4dll</guid>
      <description>&lt;p&gt;A vector database is a specialized type of database optimized for handling vector data, which is fundamental in the field of Artificial Intelligence (AI), particularly in areas like machine learning, natural language processing, and image recognition.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Vector Data?
&lt;/h2&gt;

&lt;p&gt;Vector data refers to data represented in the form of vectors. In AI, a vector often is a numerical representation of complex data, like text, images, or sound. For instance, words in natural language processing can be converted into vectors using techniques like word embeddings (e.g., Word2Vec, GloVe). These vectors capture the semantic meaning of the words and allow AI models to process and understand language.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does a Vector Database Work?
&lt;/h2&gt;

&lt;p&gt;Vector databases are designed to efficiently store and query vector data. Unlike traditional databases that perform queries based on exact matches or SQL queries, vector databases enable similarity searches. Here's how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Storing Data: Data (like text or images) is transformed into vectors using AI models and then stored in the vector database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Querying Data: When a query is made, it is also converted into a vector. The vector database then searches for vectors that are most similar to the query vector. This is known as a similarity or nearest neighbor search.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Similarity Measurement: The similarity between vectors is usually calculated using metrics like Euclidean distance, cosine similarity, or Manhattan distance. The choice of metric depends on the specific application and the nature of the data.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Correlation with AI
&lt;/h2&gt;

&lt;p&gt;The use of vector databases is highly correlated with AI for several reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Enhanced AI Models: They enable AI models to access large amounts of relevant, context-rich data quickly. This is crucial for models that require contextual understanding, like chatbots or recommendation systems.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieval Augmented Generation (RAG): This is a technique where, before generating a response, an AI model retrieves relevant information from a vector database. This helps in providing more accurate and context-aware outputs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Efficiency in Handling High-Dimensional Data: AI often deals with high-dimensional data (like images or complex text). Vector databases are optimized for such data, ensuring efficient storage and retrieval, which is a challenge in traditional databases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Real-Time Processing: In many AI applications, real-time response is crucial. Vector databases allow for quick retrieval of similar data, enabling real-time processing in AI applications.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In summary, vector databases play a crucial role in the AI ecosystem by enabling efficient storage and retrieval of vectorized data. They support AI models by providing a means to quickly access large volumes of contextually relevant data, which is essential for tasks requiring understanding and interpretation of complex data sets.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Spring IA
&lt;/h2&gt;

&lt;p&gt;The Spring AI project aims to streamline the development of applications that incorporate artificial intelligence functionality without unnecessary complexity. On this example we use features like: Embedding, Prompts, ETL and save all embedding on &lt;a href="https://github.com/pgvector/pgvector" rel="noopener noreferrer"&gt;PGvector&lt;/a&gt;(Postgres Vector database)&lt;/p&gt;

&lt;h3&gt;
  
  
  Embedding
&lt;/h3&gt;

&lt;p&gt;As a software engineer, when you're working with the &lt;strong&gt;Embeddings&lt;/strong&gt; API, think of the &lt;strong&gt;EmbeddingClient&lt;/strong&gt; interface as a bridge connecting your application to the power of AI-based text analysis. Its main role is to transform textual information into a format that machines can understand - numerical vectors, known as embeddings. These vectors are instrumental in tasks like understanding the meaning of text (semantic analysis) and sorting text into categories (text classification).&lt;/p&gt;

&lt;p&gt;From a software engineering perspective, the EmbeddingClient interface is built with two key objectives:&lt;/p&gt;

&lt;p&gt;Portability: The design of this interface is like a universal adapter in the world of embedding models. It's crafted to fit seamlessly with various embedding techniques. This means, as a developer, you can easily switch from one embedding model to another without having to overhaul your code. This flexibility is in sync with the principles of modularity and interchangeability, much like how Spring framework operates.&lt;br&gt;
Simplicity: With methods like embed(String text) and embed(Document document), EmbeddingClient takes the heavy lifting off your shoulders. It converts text to embeddings without requiring you to get tangled in the complexities of text processing and embedding algorithms. This is particularly beneficial for those who are new to the AI field, allowing them to leverage the power of embeddings in their applications without needing a deep dive into the technicalities.&lt;br&gt;
In essence, as a software engineer, when you use EmbeddingClient, you're leveraging a tool that not only simplifies the integration of advanced AI capabilities into your applications but also ensures that your code remains agile and adaptable to various embedding models.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Prompts
&lt;/h3&gt;

&lt;p&gt;Working with Spring AI, you can  &lt;strong&gt;prompts&lt;/strong&gt; can be thought of as the steering wheel for AI models, guiding them to produce specific outputs. The way these prompts are crafted plays a critical role in shaping the responses you get from the AI.&lt;/p&gt;

&lt;p&gt;To draw a parallel with familiar concepts in software development, handling prompts in Spring AI is akin to how you manage the "View" component in the Spring MVC framework. In this scenario, creating a prompt is much like constructing an elaborate text template, complete with placeholders for dynamic elements. These placeholders are then substituted with actual data based on user input or other operations within your application, similar to how you might use placeholders in SQL queries.&lt;/p&gt;

&lt;p&gt;As Spring AI continues to evolve, it aims to introduce more sophisticated methods for interacting with AI models. At its core, the current classes and functionalities in Spring AI could be compared to JDBC in terms of their fundamental role. For example, the ChatClient class in Spring AI can be likened to the essential JDBC library provided in the Java Development Kit (JDK).&lt;/p&gt;

&lt;p&gt;Building on this foundation, just as JDBC is enhanced with utilities like JdbcTemplate and Spring Data Repositories, Spring AI is expected to offer analogous helper classes. These would streamline interactions with AI models, much like how JdbcTemplate simplifies JDBC operations.&lt;/p&gt;

&lt;p&gt;Looking further ahead, Spring AI is poised to introduce even more advanced constructs. These might include elements like ChatEngines and Agents that are capable of considering the history of interactions with the AI model. This progression mirrors the way that software development has evolved from direct JDBC usage to more abstract and powerful tools like ORM frameworks.&lt;/p&gt;

&lt;p&gt;In summary, as a software engineer working with Spring AI, you are at the forefront of integrating AI capabilities into applications, using familiar paradigms and patterns from traditional software development, but applied to the cutting-edge field of AI and machine learning.&lt;/p&gt;

&lt;h3&gt;
  
  
  ETL pipeline
&lt;/h3&gt;

&lt;p&gt;Extract, Transform, and Load (ETL) framework is crucial in managing data processes in the Retrieval Augmented Generation (RAG) scenario. Essentially, the ETL pipeline is the mechanism that streamlines the journey of data from its raw state to a more organized vector store. This process is vital for preparing the data in a way that makes it easily retrievable and usable by the AI model.&lt;/p&gt;

&lt;p&gt;In the RAG use case, the core objective is to enhance the capabilities of generative AI models. This is achieved by integrating text-based data, which involves sourcing relevant information from a dataset to improve both the quality and the contextual relevance of the outputs generated by the model. The ETL framework plays a pivotal role in this process by ensuring that the data is not only accurately extracted and transformed but also efficiently loaded and stored for optimal retrieval by the AI system. This process enhances the AI's ability to produce more precise and contextually rich responses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Details of Project
&lt;/h2&gt;

&lt;p&gt;We've developed a project that incorporates fundamental principles related to AI and the Spring library, focusing on concepts like Prompts, Embedding, ETL pipelines, and Vector Databases. Our aim is to provide a concise overview of each concept's functionality. The main goal is to integrate all these elements through a practical example and apply them to a routine solution.&lt;/p&gt;

&lt;p&gt;The first step is to select a Vector Database for our use. Spring AI offers integration with various databases. In this instance, we've chosen to use &lt;strong&gt;&lt;a href="https://github.com/pgvector/pgvector" rel="noopener noreferrer"&gt;pgvector&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

version: '3.7'
services:
  postgres:
    image: ankane/pgvector:v0.5.0
    restart: always
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=admin
      - POSTGRES_DB=vector_db
      - PGPASSWORD=admin
    logging:
      options:
        max-size: 10m
        max-file: "3"
    ports:
      - '5433:5432'
    healthcheck:
      test: "pg_isready -U postgres -d vector_db"
      interval: 2s
      timeout: 20s
      retries: 10


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

&lt;/div&gt;

&lt;p&gt;for running pgvector you will run&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

docker compose up -d


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

&lt;/div&gt;

&lt;p&gt;In the project for use all Spring IA functionalities you will need add some dependencies: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;spring-ai.version&amp;gt;0.8.0-SNAPSHOT&amp;lt;/spring-ai.version&amp;gt;

&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.springframework.ai&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;spring-ai-openai-spring-boot-starter&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;${spring-ai.version}&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;

&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.springframework.ai&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;spring-ai-pdf-document-reader&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;${spring-ai.version}&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;

&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.springframework.ai&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;spring-ai-pgvector-store&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;${spring-ai.version}&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;We use latest version of library 0.8.0-SNAPSHOT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Command to Run application&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

mvn spring-boot:run -Dspring-boot.run.profiles=openai


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

&lt;/div&gt;

&lt;p&gt;We have divided our approach into two distinct parts: data handling and question processing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Handling&lt;/strong&gt;: This involves several key operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Loading: Importing data into our system.&lt;br&gt;
Transforming: Modifying or processing the data to fit our needs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inserting: Adding new data entries into our database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieving: Accessing data from the database as needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deleting: Removing data entries that are no longer required.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Question Processing&lt;/strong&gt;: In this part, we utilize the data that has been loaded and processed. The aim here is to provide responses that are directly related to, and informed by, the data we have in our resources.&lt;/p&gt;

&lt;p&gt;Regarding the data aspect, we have utilized a Technology Radar from ThoughtWorks as our primary data source."&lt;/p&gt;

&lt;p&gt;About data, we used a Technology Radar from Thoughtwrorks&lt;/p&gt;

&lt;h3&gt;
  
  
  Technology Radar
&lt;/h3&gt;

&lt;p&gt;The Technology Radar is a snapshot of tools, techniques, platforms, languages and frameworks based on the practical experiences of Thoughtworkers around the world. Published twice a year, it provides insights on how the world builds software today. Use it to identify and evaluate what’s important to you.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://www.thoughtworks.com/content/dam/thoughtworks/documents/radar/2023/09/tr_technology_radar_vol_29_en.pdf" rel="noopener noreferrer"&gt;Here the link from latest tech radar version&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the content from the ThoughtWorks Technology Radar as our reference, we are now equipped to utilize our API to recommend the best tools or offer insights and opinions on various technologies.&lt;/p&gt;

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

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

&lt;p&gt;&lt;a href="https://github.com/lucasnscr/SpringAI" rel="noopener noreferrer"&gt;Link of project&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>spring</category>
      <category>ai</category>
      <category>java</category>
    </item>
    <item>
      <title>Generative AI with SpringBoot Services</title>
      <dc:creator>lucasnscr</dc:creator>
      <pubDate>Wed, 31 Jan 2024 20:32:22 +0000</pubDate>
      <link>https://dev.to/lucasnscr/generative-ai-with-springboot-services-471l</link>
      <guid>https://dev.to/lucasnscr/generative-ai-with-springboot-services-471l</guid>
      <description>&lt;h1&gt;
  
  
  Spring AI
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.spring.io/spring-ai/reference/" rel="noopener noreferrer"&gt;Spring AI Docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/spring-projects/spring-ai" rel="noopener noreferrer"&gt;Spring AI Project&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Spring AI library is a set of APIs and components that allow Java developers to integrate artificial intelligence (AI) into their Spring Boot applications. The library is based on the Spring Framework and provides a unified API to access a variety of AI technologies, including machine learning, deep learning, natural language processing, and computer vision.&lt;/p&gt;

&lt;p&gt;Spring AI provides a number of features to make it easy to integrate AI into Spring Boot applications. These features include:&lt;/p&gt;

&lt;p&gt;Support for a variety of AI technologies: Spring AI supports a variety of AI technologies, including machine learning, deep learning, natural language processing, and computer vision. This allows developers to choose the AI technology that best meets their needs.&lt;br&gt;
Unified API: Spring AI provides a unified API to access all AI technologies. This simplifies the development of Spring Boot applications that integrate AI.&lt;br&gt;
Ease of use: Spring AI is designed to be easy to use. Developers can start using the library quickly, without the need to learn a new API.&lt;br&gt;
Spring AI can be used for a variety of purposes, including:&lt;/p&gt;

&lt;p&gt;Recommendations: Spring AI can be used to generate personalized recommendations for users, based on their historical data.&lt;br&gt;
Data analysis: Spring AI can be used to analyze data and identify patterns and trends.&lt;br&gt;
Anomaly detection: Spring AI can be used to detect anomalies in data, such as fraud or cyber attacks.&lt;br&gt;
Natural language processing: Spring AI can be used to process natural language, such as translation, summarization, and text generation.&lt;br&gt;
Computer vision: Spring AI can be used to process images and videos, such as object identification, image classification, and facial recognition.&lt;br&gt;
Spring AI is a powerful tool that can help developers integrate AI into their Spring Boot applications. The library is easy to use and provides support for a variety of AI technologies.&lt;/p&gt;

&lt;p&gt;Here are some additional details about the Spring AI library:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The library is still under development, but it has already been used in a variety of production applications.&lt;/li&gt;
&lt;li&gt;The library is open source and available on GitHub.&lt;/li&gt;
&lt;li&gt;The library documentation is available on the Spring website.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Project Setup
&lt;/h1&gt;

&lt;p&gt;When configuring your Maven pom.xml for the Spring AI project, add the specified repository to access its dependencies. As Spring AI is currently in the experimental phase, only snapshot versions are available. Here is how you should include this in your pom.xml:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;repositories&amp;gt;
        &amp;lt;repository&amp;gt;
            &amp;lt;id&amp;gt;spring-snapshots&amp;lt;/id&amp;gt;
            &amp;lt;name&amp;gt;Spring Snapshots&amp;lt;/name&amp;gt;
            &amp;lt;url&amp;gt;https://repo.spring.io/snapshot&amp;lt;/url&amp;gt;
            &amp;lt;releases&amp;gt;
                &amp;lt;enabled&amp;gt;false&amp;lt;/enabled&amp;gt;
            &amp;lt;/releases&amp;gt;
        &amp;lt;/repository&amp;gt;
    &amp;lt;/repositories&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;In this project, I have selected OpenAI as the primary interface. However, it's important to note that Spring AI offers a variety of different ChatClient interfaces.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAI&lt;/li&gt;
&lt;li&gt;Azure OpenAI&lt;/li&gt;
&lt;li&gt;Hugging Face&lt;/li&gt;
&lt;li&gt;Ollama&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenAI Library&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.springframework.experimental.ai&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;spring-ai-openai-spring-boot-starter&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;0.7.1-SNAPSHOT&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;The most recent version of this library is 0.8.0-SNAPSHOT. We attempted to use this version, but currently, we only have access to the 0.7.1-SNAPSHOT version. As our studies progress, we will try to update to the latest version.&lt;/p&gt;

&lt;p&gt;After all setup, you need to create your account and API key in one of the chosen clients. In my case &lt;a href="https://platform.openai.com/docs/overview" rel="noopener noreferrer"&gt;OpenAI Platform&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was just the first study with Generative AI and the Spring AI library. We will develop some other features using the library, and I hope you follow my journey with Spring and AI.&lt;/p&gt;

&lt;p&gt;Part of this doc was generated with SpringAI and Model ChatGPT 3.5.&lt;/p&gt;

&lt;h1&gt;
  
  
  Checkout this project from Github
&lt;/h1&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

git clone https://github.com/lucasnscr/SpringAI.git


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

&lt;/div&gt;

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

</description>
      <category>ia</category>
      <category>springboot</category>
      <category>java</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Deployment and Patterns</title>
      <dc:creator>lucasnscr</dc:creator>
      <pubDate>Fri, 20 Jan 2023 15:30:02 +0000</pubDate>
      <link>https://dev.to/lucasnscr/deployment-and-patterns-18me</link>
      <guid>https://dev.to/lucasnscr/deployment-and-patterns-18me</guid>
      <description>&lt;p&gt;After a few years working as a Software Engineer, I received an invitation to work as an SRE and closer to my company's CI/CD processes. I think the beginning would be ideal to understand the main concepts and patterns. I believe patterns are ways to solve problems and ensure a robust solution for our service, product, platform or APIs. Today I intend to talk about deployments, but from the perspective of the Continuous Delivery process and talk about the main patterns of this technique.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is Continuous Delivery?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Continuous Delivery is the ability to get changes of all types including new features, configuration changes, bug fixes and experiments—into production, or into the hands of users, safely and quickly in a sustainable way.&lt;/p&gt;

&lt;p&gt;Our goal is to make deployments—whether of a large-scale distributed system, a complex production environment, an embedded system, or an app—predictable, routine affairs that can be performed on demand.&lt;/p&gt;

&lt;p&gt;Continuous Delivery improve some features in lifecyle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Low risk releases. The primary goal of continuous delivery is to make software deployments painless, low-risk events that can be performed at any time, on demand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Faster time to market. It’s not uncommon for the integration and test/fix phase of the traditional phased software delivery lifecycle to consume weeks or even months.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Higher quality. When developers have automated tools that discover regressions within minutes, teams are freed to focus their effort on user research and higher level testing activities such as exploratory testing, usability testing, and performance and security testing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lower costs. Any successful software product or service will evolve significantly over the course of its lifetime. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better products. Continuous delivery makes it economic to work in small batches. This means we can get feedback from users throughout the delivery lifecycle based on working software. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Deployment Pipeline&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The key pattern introduced in continuous delivery is the deployment pipeline. This pattern emerged from several ThoughtWorks projects where we were struggling with complex, fragile, painful manual processes for preparing testing and production environments and deploying builds to them. We’d already worked to automate a significant amount of the regression and acceptance testing, but it was taking weeks to get builds to integrated environments for full regression testing, and our first deployment to production took an entire weekend.&lt;/p&gt;

&lt;p&gt;We wanted to industrialize the process of taking changes from version control to production. Our goal was to make deployment to any environment a fully automated, scripted process that could be performed on demand in minutes (on the original project we got it down to less than an hour, which was a big deal for an enterprise system in 2005). We wanted to be able to configure testing and production environments purely from configuration files stored in version control. The apparatus we used to perform these tasks (usually in the form of a bunch of scripts in bash or ruby) became known as deployment pipelines, which Dan North, Chris Read and I wrote up in a paper presented at the Agile 2006 conference.&lt;/p&gt;

&lt;p&gt;In the deployment pipeline pattern, every change in version control triggers a process (usually in a CI server) which creates deployable packages and runs automated unit tests and other validations such as static code analysis. This first step is optimized so that it takes only a few minutes to run. If this initial commit stage fails, the problem must be fixed immediately—nobody should check in more work on a broken commit stage. Every passing commit stage triggers the next step in the pipeline, which might consist of a more comprehensive set of automated tests. Versions of the software that pass all the automated tests can then be deployed on demand to further stages such as exploratory testing, performance testing, staging, and production, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NJLuFjbX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jqnet7hd8mopna7jscca.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NJLuFjbX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jqnet7hd8mopna7jscca.png" alt="pipeline description" width="880" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is Deployment?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Deployment in software and web development means pushing changes or updates from one deployment environment to another. When setting up a website you will always have your live website, which is called the live environment or production environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Deployment Patterns&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Deployment patterns are techniques used to introduce new features or updates to an application in a controlled and organized manner. The goal is to minimize downtime, ensure that the new features are stable and perform well, and sometimes allow for testing with a small group of users before making the update available to everyone.&lt;/p&gt;

&lt;p&gt;There are some deployment patterns and in this text we will mention the positive and negative points of each one, I will only mention the ones I had contact with either as a Software Engineer or as an SRE: Canary, Blue and Green, Dark Launching and A/B Testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Canary Release&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fLcDeWAr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6kttphaq1rdigkrzu0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fLcDeWAr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6kttphaq1rdigkrzu0i.png" alt="canary demonstration" width="880" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A canary deployment is a method that exposes a new feature to an early sub-segment of users. The goal is to test new functionality on a subset of customers before releasing it to the entire user base.&lt;/p&gt;

&lt;p&gt;You can choose randomly or a specific group of users and roll back if anything breaks. If everything works as intended, you can gradually add more users while monitoring logs, errors, and software health.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we used&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Service Evaluation: You can evaluate multiple service versions side by side using canary deployments in real-world environments with actual users and use cases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cost effective: Because two production environments are not required, it is less expensive than a blue-green deployment.&lt;br&gt;
Testing: Canary deployment can be used for A/B testing as it offers two alternatives to the users and selects one with better reception.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In-built Capacity Test: Normally, it is difficult to test the capacity of a large production environment. Canary deployments offer in-built capacity tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Feedback: With the release being made for targeted or a sample number of users, you receive invaluable input from real users and modify canary versions for improvements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No cold-starts: Unlike new systems that take a while to start, Canary deployments build up momentum to prevent slowness of cold-start.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zero downtime: Just like blue-green deployments, a canary deployment does not cause downtime.&lt;br&gt;
Simple Rollback Mechanism: You can always easily roll back to the previous version.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why we not used&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Script Testing: Canary release scripting is challenging, since human verification and testing can take a significant amount of time, and the monitoring and instrumentation that is required for production testing may call for further research.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Complexity: Canary deployments share the same complexities as blue-green deployments like many production machines, user migrations, and system monitoring&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Time: It takes time to set up a healthy canary deployment pipeline. However, once done right, you can do more frequent and safer deployments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deployment at an enterprise scale: An enterprise Canary deployment is difficult to accomplish in an environment where the software is loaded on personal devices. Setting up an auto-update environment for end users may be one method to get around this.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Blue/Green Deployment&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VGx7g0vS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gwtrdpcro94vyhmm9p37.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VGx7g0vS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gwtrdpcro94vyhmm9p37.jpeg" alt="blue green description" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Blue green deployment is an application release model that gradually transfers user traffic from a previous version of an app or microservice to a nearly identical new release—both of which are running in production. &lt;/p&gt;

&lt;p&gt;The old version can be called the blue environment while the new version can be known as the green environment. Once production traffic is fully transferred from blue to green, blue can standby in case of rollback or pulled from production and updated to become the template upon which the next update is made.&lt;/p&gt;

&lt;p&gt;There are downsides to this continuous deployment model. Not all environments have the same uptime requirements or the resources to properly perform CI/CD processes like blue green. But many apps evolve to support such continuous delivery as the enterprises supporting them digitally transform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we used&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Rapid releasing: You can release software practically any time. You don't need to schedule a weekend or off-hours release because, in most cases, all that is necessary to go live is a routing change. Because there is no associated downtime, these deployments have no negative impact on users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simple rollbacks: The reverse process is equally fast. Because blue-green deployments utilize two parallel production environments, you can quickly flip back to the stable one should any issues arise in your live environment. This reduces the risks inherent in experimenting in production.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Built-in disaster recovery: Because blue-green deployments use two production environments, they implicitly offer disaster recovery for your business systems. A dual production environment is its own hot backup.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Load balancing: Blue-green parallel production environments also make load balancing easy. When the two environments are functionally identical, you can use a load balancer or feature toggle in your software to route traffic to different environments as needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we not used&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resource-intensive: As is evident by now, to perform a blue-green deployment, you will need to resource and maintain two production environments. The costs of this, in money and sysadmin time, might be too high for some organizations. For others, they may only be able to commit such resources for their highest value products. If that is the case, does the DevOps team release software in a CI/CD model for some products but not others? That may not be sustainable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Dark Launching&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NA9ZsoNb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xff7uql5fjau3qef33vl.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NA9ZsoNb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xff7uql5fjau3qef33vl.jpeg" alt="Dark launching" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A dark launch or dark release is a term that refers to releasing your features to a subset of users to gather their feedback and improve your new features accordingly. Hence, it is a way to deploy a feature but limit access to it to obtain useful feedback.&lt;/p&gt;

&lt;p&gt;You can think of it as a safe way to release your features to a small set of users to test whether they like this new feature.&lt;/p&gt;

&lt;p&gt;Based on the feedback received from these users, you would either release this feature to the rest of your users or you work on optimizing and improving the feature before doing a full release.&lt;/p&gt;

&lt;p&gt;Feature toggles — also known as feature flags — allow you to further decouple the deployment of different software versions from the release of features to users. You can deploy new versions of an application as often as needed, with certain features disabled: releasing a feature to users is simply a matter of toggling it “on.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lucasnscr/ff4j-Security-Jdbc"&gt;Here one implementations of feature flag&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we used&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;More experimentation: Dark launches are a great way to gauge customers’ interest in a new feature you’re planning to release. It gives product teams in particular a way to test out their ideas with less risk as only a select number of users are seeing the feature. Teams can choose to run experiments for both front- and back-end features and then release the winning variation to everyone else.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Higher quality releases and faster time to market: uch a technique allows you to put forward high-quality releases as you are updating your features according to feedback from your most relevant users. It allows developers to see how users respond to and interact with the new features to determine whether any improvements will need to be made. Thus, a dark launch is a way to test your new feature in a production environment with real world users. This way, you’ll be able to gather essential metrics to analyze feature performance and to closely monitor how your users engage with the feature.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why we not used&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Microservices are behind feature toggles, which can lead to increased costs and time for debugging microservices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Additionally, to enable continuous development, teams must be able to move microservices behind feature toggles during development itself.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;A/B Testing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2vM_Pc7q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bgn8wm1fwewh2p30wd9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2vM_Pc7q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bgn8wm1fwewh2p30wd9j.png" alt="A/B testing description" width="880" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A/B Testing, also known as Split Testing or Bucket Testing, compares two variants of the same webpage or app and finds out which one will give better results. It is an experiment where two or more versions of the page are shown to the user randomly. Using statistical methods, which one will be better for a particular goal is determined. This eliminates guesswork and allows data-driven decisions, which results in more conversions and sales.&lt;/p&gt;

&lt;p&gt;In the A/B test, a web page or an app screen is taken and modified to create another version of the same. The change can be as small as a button change or a complete revamp. Half of the site traffic is shown in the page’s original version(known as control), and the other half is shown the modified version(known as a variation) of the page. Data is collected with each engagement and analyzed with statistical software. It can be determined whether the change had a positive, negative or neutral effect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we used&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Get clear evidence: It’s easy to see how many users complete a transaction with site A over site B. The evidence is based on real behaviour, so is hard data of the type that money men love (and can be presented in a simple-looking, hard hitting chart).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test new ideas: If you have an innovative idea for an existing site, A/B testing provides hard proof as to whether it works or not. However, you will need to implement that big idea in hard code before you can test it this way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optimise one step at a time: If you run a large site, or many sites, then A/B testing is a fantastic opportunity to “patch” test, by starting out in a small corner and then working up to the main pages of the site. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why we not used&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Can take lots of time and resources: A/B testing can take a lot longer to set up than other forms of testing. Setting up the A/B system can be a resource and time hog, although third-party services can help. Depending on the company size, there may be endless meetings about which variables to include in the tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only works for specific goals: This kind of testing is ideal if you want to solve one dilemma, which product page gives me the best results? But, if your goals are less easy to measure pure A/B testing won’t provide those answers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Could end up with constant testing: Once the test is over, that is it. The data is useless for anything else. Further A/B tests will have to start from a new baseline and other types of testing will only likely be applied to the more successful site, when they could have found equally useful information from the rejected version.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>patterns</category>
      <category>aws</category>
    </item>
    <item>
      <title>Database types and Cap Theorem</title>
      <dc:creator>lucasnscr</dc:creator>
      <pubDate>Wed, 04 Jan 2023 22:56:52 +0000</pubDate>
      <link>https://dev.to/lucasnscr/database-types-and-cap-theorem-56d9</link>
      <guid>https://dev.to/lucasnscr/database-types-and-cap-theorem-56d9</guid>
      <description>&lt;p&gt;&lt;strong&gt;NoSQL&lt;/strong&gt; databases are a class of persistence technology that provide a new storage mechanism that goes hand in hand with normalization and relational databases. Like any other database, it has the same objectives: inserting, updating, retrieving and deleting information, however, with new modeling concepts and storage structure.&lt;/p&gt;

&lt;p&gt;The term NoSQL, initially, was related to "not SQL" and later it was controlled to Not Only SQL, that is, "not just SQL", opening the concept of polyglot awareness (the work of dealing with different types of databases to reach the objectives in the application).&lt;/p&gt;

&lt;p&gt;These databases have speed and high scalability rates as their main characteristics, such as the ease of increasing the number of database servers. This prevents the bottleneck of operations, avoids a point of failure, in addition to geographically distributing them, making the data closer to the users who respond to the request.&lt;/p&gt;

&lt;p&gt;NoSQL databases are being adopted more frequently in different types of applications, including financial institutions. As a consequence, the number of suppliers for this type of database is also growing.&lt;/p&gt;

&lt;p&gt;Currently, NoSQL databases are classified into four groups (key-value, column family, document and graphs) defined by their storage model:&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Value
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2ydlimhxtibtmxcwqw2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2ydlimhxtibtmxcwqw2.png" alt="key-value description" width="403" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key-value databases have a structure similar to java.util.Map , that is, the information will be retrieved only by the key. This type of database can be used, for example, to manage the user's session. Another interesting case is DNS, whose key is the address, for example &lt;a href="http://www.google.com" rel="noopener noreferrer"&gt;www.google.com&lt;/a&gt; , and the value is the IP of that server.&lt;/p&gt;

&lt;p&gt;Currently, there are several key-value database implementations, among which the most famous are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;li&gt;Amazon DynamoDB&lt;/li&gt;
&lt;li&gt;Amazon S3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comparing the relational database with the key-value type, it is possible to perceive some points. One is that the key-value structure is quite simple.&lt;/p&gt;

&lt;p&gt;It is not possible to perform operations such as joining between buckets and the value is composed of a large block of information instead of being subdivided into columns as in the database relational.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Relational Database&lt;/th&gt;
&lt;th&gt;Key-Value Database&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Table&lt;/td&gt;
&lt;td&gt;Bucket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Row&lt;/td&gt;
&lt;td&gt;Key/Value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Column&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Relationship&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Column Database
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fayrcxyuuuwqfk2kj3rub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fayrcxyuuuwqfk2kj3rub.png" alt="Column description" width="533" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This model became popular through &lt;strong&gt;Google's BigTable&lt;/strong&gt; paper, with the aim of setting up a distributed data storage system, and designed to have a high degree of scalability and data volume. Just like the key-value, to perform a search or retrieve some information within the database, it is necessary to use the field that works as a unique identifier that would be similar to the key in the key-value structure. However, the similarities end there. Information is grouped into columns: a unit of information that is made up of the name and the information itself.&lt;/p&gt;

&lt;p&gt;These types of databases are important when dealing with a high degree of data volume, such that information needs to be distributed across multiple servers. But it is worth mentioning that its reading operation is quite limited, similar to the key-value, since the search for information is defined from a single field or a key. There are several databases that use these structures, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hbase &lt;/li&gt;
&lt;li&gt;Cassandra &lt;/li&gt;
&lt;li&gt;Scylla&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Among the types of column family type databases, Apache Cassandra is the most famous. Thus, if an application needs to deal with a large volume of data and with easy scalability, Cassandra is certainly a good option.&lt;/p&gt;

&lt;p&gt;By contrasting the column family type database with relational databases, it is possible to notice that operations, in general, are much faster. It is simpler to work with large volumes of information and servers distributed all over the world, however, this comes at a cost: the reading of this type of database is very limited.&lt;/p&gt;

&lt;p&gt;For example, it is not possible to perform unions between column families as in the relational database. The column family allows you to have an unlimited number of columns, which in turn are composed of name and information, exactly as shown in the following table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Relational Database&lt;/th&gt;
&lt;th&gt;Column Database&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Table&lt;/td&gt;
&lt;td&gt;Column Family&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Row&lt;/td&gt;
&lt;td&gt;Column&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Column&lt;/td&gt;
&lt;td&gt;Name and Value to Column&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Relationship&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Document Database
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flhxhnff15bos36f8tt9l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flhxhnff15bos36f8tt9l.png" alt="Document description" width="754" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Document-oriented databases are very similar in structure to a JSON or XML file. They are composed of a large number of fields, which are created at runtime, generating great flexibility, both for reading and writing information. They allow the reading of information by fields other than the key. &lt;/p&gt;

&lt;p&gt;Some implementations, for example, have very high integration with search engines. Thus, this type of database is crucial when performing data analysis or system logs. There are a few implementations of document-type databases, the most famous of which is MongoDB.&lt;/p&gt;

&lt;p&gt;When comparing with a relational database, although it is possible to perform a search for fields other than the unique identifier, document-type databases do not support relationships. Another point is that document-type banks, in general, are schemaless.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Relational Database&lt;/th&gt;
&lt;th&gt;Document Database&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Table&lt;/td&gt;
&lt;td&gt;Collection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Row&lt;/td&gt;
&lt;td&gt;Document&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Column&lt;/td&gt;
&lt;td&gt;Key/Value pair&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Relationship&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Graphs Database
&lt;/h2&gt;

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

&lt;p&gt;Graph databases are a data structure that connects a set of vertices through a set of edges. Modern databases in this category support &lt;strong&gt;multi relational&lt;/strong&gt; graph structures, where there are different types of vertices (representing people, places, items) and different types of edges. The recommendation systems that take place on social networks are the biggest case for the graph-type bank. Of the most famous database types in the NoSQL world, the graph has a distinct structure with the relational one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Neo4j&lt;/li&gt;
&lt;li&gt;HyperGraphDB&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Relational Database&lt;/th&gt;
&lt;th&gt;Document Database&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Table&lt;/td&gt;
&lt;td&gt;Collection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Row&lt;/td&gt;
&lt;td&gt;Document&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Column&lt;/td&gt;
&lt;td&gt;Key/Value pair&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Relationship&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Cap Theorem
&lt;/h2&gt;

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

&lt;p&gt;One of the great challenges of NoSQL databases is that they deal with distributed persistence, that is, the information is located on more than one server. Several studies have been created to help with this distributed persistence challenge, the most famous being a theory created in 1999, the CAP Theorem.&lt;/p&gt;

&lt;p&gt;This theorem states that it is impossible for distributed data storage to simultaneously provide more than two of the following three guarantees:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency&lt;/strong&gt;: A guarantee that every node in a distributed cluster returns the same most recent and successful write. Consistency refers to each customer having the same view of the data. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Availability&lt;/strong&gt;: each request receives a response (no error) - no guarantee that it contains the most recent write.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Partition tolerance&lt;/strong&gt;: The system continues to function and maintain its consistency guarantees despite network partitions. Distributed systems that guarantee tolerance continue to operate even if there is a failure in one of the nodes, since there is at least one node to operate the same job and guarantee the functioning of the system.&lt;/p&gt;

&lt;p&gt;In general, this theorem explains that there is no perfect world. When you choose one characteristic, you lose another as a consequence. In an ideal world, a distributed database would be able to support all three features, but in reality, it is important for the developer to know what he will be missing out on when choosing between one or the other.&lt;/p&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>Aws Lambda - Implementing lambda with Spring native and localstack</title>
      <dc:creator>lucasnscr</dc:creator>
      <pubDate>Thu, 22 Sep 2022 21:49:21 +0000</pubDate>
      <link>https://dev.to/lucasnscr/aws-lambda-implementing-lambda-with-spring-native-and-localstack-58e4</link>
      <guid>https://dev.to/lucasnscr/aws-lambda-implementing-lambda-with-spring-native-and-localstack-58e4</guid>
      <description>&lt;h1&gt;
  
  
  Serverless Architecture with Spring Native
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Serveless Architecture
&lt;/h3&gt;

&lt;p&gt;Serverless differs from other cloud computing models in that the cloud provider is responsible for managing both the cloud infrastructure and the scaling of apps. Serverless apps are deployed in containers that automatically launch on demand when called.&lt;/p&gt;

&lt;p&gt;Under a standard Infrastructure-as-a-Service (IaaS) cloud computing model, users prepurchase units of capacity, meaning you pay a public cloud provider for always-on server components to run your apps. It’s the user’s responsibility to scale up server capacity during times of high demand and to scale down when that capacity is no longer needed. The cloud infrastructure necessary to run an app is active even when the app isn’t being used.&lt;/p&gt;

&lt;p&gt;With serverless architecture, by contrast, apps are launched only as needed. When an event triggers app code to run, the public cloud provider dynamically allocates resources for that code. The user stops paying when the code finishes executing. In addition to the cost and efficiency benefits, serverless frees developers from routine and menial tasks associated with app scaling and server provisioning.&lt;/p&gt;

&lt;p&gt;With serverless, routine tasks such as managing the operating system and file system, security patches, load balancing, capacity management, scaling, logging, and monitoring are all offloaded to a cloud services provider.&lt;/p&gt;

&lt;p&gt;It’s possible to build an entirely serverless app, or an app composed of partially serverless and partially traditional microservices components.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Native Image
&lt;/h3&gt;

&lt;p&gt;Native image is a technology that allows you to compile Java code in advance and make it executable. This executable contains application classes, their dependency classes, runtime library classes, and native code linked to the JDK. After the build process, it builds the executable for the operating system, this process is called image build. JVM-based languages have this capability like Java, Scala, Clojure and Kotlin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spring Native
&lt;/h3&gt;

&lt;p&gt;In March 2021, Pivotal released a still-experimental version to the community of its native module, Spring-Native. Given that its competitors are already able to have a more fluid integration with GraalVM, spring had to chase after Quarkus and Micronaut to be able to make its stack compatible with native images.&lt;/p&gt;

&lt;p&gt;Spring Native provides the ideal workload for computing in containers and Kubernetes. Use strong native image an instant boot, instant peak performance and reduced memory consumption.&lt;/p&gt;

&lt;p&gt;As everything is not perfect, it is necessary to understand that there are steps in this process that need to be improved, as the process of generating a native image is very heavy and time-consuming.&lt;/p&gt;

&lt;h3&gt;
  
  
  Environment/Localstack
&lt;/h3&gt;

&lt;p&gt;We use &lt;em&gt;Localstack&lt;/em&gt; for emulate on local machine our Aws environment. To start the localstack in the repository have a file docker-compose.yml&lt;/p&gt;

&lt;p&gt;For start localstack running this command: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

docker-compose up -d


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Necessary Steps
&lt;/h3&gt;

&lt;p&gt;Running the command below: &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

mvn -ntp clean package -Pnative --settings ./settings-spring-native.xml


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

&lt;/div&gt;

&lt;p&gt;Command for create docker of the application using:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

mvn spring-boot:build-image --settings ./settings-spring-native.xml



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

&lt;/div&gt;

&lt;p&gt;Command for crate S3 bucket:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

aws s3 mb s3://native-bucket --endpoint-url http://localhost:4566


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

&lt;/div&gt;

&lt;p&gt;Command for create Aws Lambda(Function1):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

aws lambda create-function \
--endpoint-url http://localhost:4566 \
--function-name function1 \
--runtime java17 \
--handler function1.S3Handler \
--region us-east-1 \
--zip-file fileb://function1-0.0.1-SNAPSHOT.jar \
--role arn:aws:iam::12345:role/ignoreme


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

&lt;/div&gt;

&lt;p&gt;Command for create Aws Lambda(Function2):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

aws lambda create-function \
--endpoint-url http://localhost:4566 \
--function-name function2 \
--runtime java17 \
--handler function2.S3Handler \
--region us-east-1 \
--zip-file fileb://function2-0.0.1-SNAPSHOT.jar \
--role arn:aws:iam::12345:role/ignoreme


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

&lt;/div&gt;

&lt;p&gt;Following all the steps, when we execute the command receive the return with this message:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
    "FunctionName": "function1",
    "FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:function1",
    "Runtime": "java17",
    "Role": "arn:aws:iam::12345:role/ignoreme",
    "Handler": "function1.S3Handler",
    "CodeSize": 91807,
    "Description": "",
    "Timeout": 3,
    "LastModified": "2022-09-25T18:10:57.187+0000",
    "CodeSha256": "JDYOPtjvkoP17EKU5Fhu45GGFrDve0tJSe2iRccEb9g=",
    "Version": "$LATEST",
    "VpcConfig": {},
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "1acedcab-1c5d-4b33-932a-bc2e6a2a67da",
    "State": "Active",
    "LastUpdateStatus": "Successful",
    "PackageType": "Zip",
    "Architectures": [
        "x86_64"
    ]


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Registering our Lambda to S3 bucket events&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally, we need to bind the lambda to the put-bucket-notification event within LocalStack. Any time that an object is created within our native-image S3 bucket, it will invoke our earlier Java code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function1&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

aws s3api put-bucket-notification-configuration --bucket native-image --notification-configuration file://s3hook.json --endpoint-url http://localhost:4566


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Invoking a Lambda within LocalStack&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a simple text file called samplefile.txt and run the following command to transfer the file to S3, thereby triggering the Lambda:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

aws s3 cp uploadfile.txt s3://native-bucket/uploadfile.txt --endpoint-url http://localhost:4566


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

&lt;/div&gt;

&lt;p&gt;Time to start/running the functions with spring native.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;INFO 38045 --- [main] c.l.s.f.Function1ApplicationTests : Started Function1ApplicationTests in 0.64 seconds (JVM running for 1.13)&lt;/p&gt;

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

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Project description&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Project design and architecture.&lt;/p&gt;

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

&lt;h1&gt;
  
  
  Checkout this project from Github
&lt;/h1&gt;

&lt;p&gt;git clone &lt;a href="https://github.com/lucasnscr/serverless-spring-native" rel="noopener noreferrer"&gt;https://github.com/lucasnscr/serverless-spring-native&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>java</category>
      <category>spring</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
