Quarkus LangChain4j

repository·main·Indexed 43 days ago

https://github.com/quarkiverse/quarkus-langchain4j

Extensions that facilitate seamless integration between the Quarkus framework and the LangChain4j library, enabling developers to incorporate Large Language Models (LLMs) into Quarkus applications. Features include declarative AI services, support for OpenAI GPTs, Hugging Faces, and Ollama, document store integration with Redis, Chroma, and Infinispan, GraalVM native compilation support, and integrated observability.

Tokens
165.9K
Snippets
537
Records
669
Agent score
54%

What's inside Quarkus LangChain4j

  1. Overview of Quarkus LangChain4j features

    main

    Quarkus LangChain4j provides seamless integration between Quarkus and LangChain4j, allowing you to incorporate Large Language Models (LLMs) into your applications with the following capabilities:

    • Declarative AI services: Define AI services using interfaces.
    • Diverse LLM Integration: Support for OpenAI GPTs, Hugging Faces, Ollama, and more.
    • Tool & Embedding Support: Use LLMs with external tools and embedding models.
    • Document Store Integration: Connect to stores like Redis, Chroma, and Infinispan.
    • Quarkus Native Support: Compatible with GraalVM native compilation.
    • Observability: Integrated with the Quarkus observability stack (metrics, tracing).
    • Pluggable Auth: Support for various authentication providers.
  2. Overview of Quarkus LangChain4j

    main

    Quarkus LangChain4j is an extension that integrates Large Language Models (LLMs) into Quarkus applications using a declarative, developer-friendly API. It is built on top of the LangChain4j library but provides an opinionated, enterprise-grade integration tailored for the Quarkus ecosystem.

    Key Capabilities:

    • Declarative AI Services: Use Java interfaces and annotations to call LLMs with minimal boilerplate.
    • Optimized for Quarkus: Fast startup, native-image ready, and low footprint.
    • Advanced AI Patterns: Support for tool calling (function calling), agentic patterns, and chat memory for multi-turn interactions.
    • RAG Support: Easy integration with vector stores like Redis, Chroma, and Infinispan for Retrieval-Augmented Generation.
    • Built-in Observability: Integrated logs, metrics, and tracing.
    • Developer Experience: Includes Dev UI for visual introspection and Dev Services for automatic embedding stores and model serving.
  3. Use Milvus as an embedding store in Quarkus LangChain4j

    main

    The quarkus-langchain4j-milvus extension allows you to use Milvus as a vector database for storing and retrieving embedded documents in RAG (Retrieval-Augmented Generation) applications. It supports approximate nearest neighbor (ANN) search using COSINE, L2 (Euclidean), or IP (Inner Product) distance metrics. The extension automatically handles collection and schema initialization via gRPC.

    include::{examples-dir}/io/quarkiverse/langchain4j/samples/IngestorExampleWithMilvus.java[]
  4. A2A Agent Discovery via Apicurio Registry

    main

    This sample demonstrates dynamic Agent-to-Agent (A2A) discovery using Apicurio Registry as a centralized store for agent cards.

    In this pattern, a 'Classifier' agent (using a local LLM) receives a request and determines which specialized agent should handle it. Instead of using hardcoded URLs or compile-time dependencies, the system discovers specialized agents (e.g., billing, technical, shipping) at runtime by querying the Apicurio Registry for artifacts of type AGENT_CARD. These agents are then accessed via the @RegistryAgent annotation, which acts as an A2A client.

    Customer Request
           │
           ▼
    ┌──────────────┐     ┌───────────────────┐
    │  Classifier  │────▶│ Apicurio Registry │
    │  (local LLM) │     │  ┌─────────────┐  │
    └──────────────┘     │  │billing-agent│  │
           │             │  │tech-agent   │  │
           ▼             │  │ship-agent   │  │
    ┌──────────────┐     │  └─────────────┘  │
    │ @RegistryAgent│◀───│   AGENT_CARD      │
    │  (A2A client) │     └───────────────────┘
    └──────────────┘
  5. What is Semantic Compression and when to use it

    main

    Semantic compression is a strategy to manage long chat histories by using an LLM to summarize messages in place, rather than simply truncating or evicting them. This approach preserves critical context (names, dates, action items) while staying within the model's token limits.

    Key Benefits

    • Prevents Token-Limit Errors: Avoids failed requests caused by exceeding the model's context window.
    • Reduces Cost and Latency: Shortens prompts, which lowers API costs and improves response times.

    Implementation Strategy

    In Quarkus LangChain4j, you implement semantic compression by providing a custom ChatMemoryStore CDI bean. This bean wraps an existing memory store, monitors the history length or token count against a threshold, and triggers a summarization model when the threshold is exceeded. The summary is then embedded into a system message to maintain continuity.

    Warning: Semantic compression only applies to textual chat memories. Do not use this strategy for vision or other non-text data.

  6. Configure multiple named Neo4j embedding stores

    main

    You can manage embeddings for different domains by configuring multiple named stores. Each store can have its own dimension, label, index name, and database.

    Important Isolation Rules:

    • All named stores share the same org.neo4j.driver.Driver and connect to the same Neo4j instance.
    • To keep data isolated within a single database (Neo4j Community Edition), use a distinct label, index-name, and embedding-property per store.
    • To use different databases, you must have Neo4j Enterprise Edition. On Community Edition, you must set database-name to neo4j.

    Configuration Example: To configure a store named products:

    quarkus.langchain4j.neo4j.products.database-name=neo4j
    quarkus.langchain4j.neo4j.products.dimension=1536
    quarkus.langchain4j.neo4j.products.label=Product
    quarkus.langchain4j.neo4j.products.index-name=product_vector

    Injection: Use the @EmbeddingStoreName qualifier to inject a specific named store:

    @Inject
    @EmbeddingStoreName("products")
    EmbeddingStore<TextSegment> productsStore;

    Disabling Stores:

    • Disable the default store: quarkus.langchain4j.neo4j.default-store-enabled=false
    • Skip a specific named store at build time: quarkus.langchain4j.neo4j.<store-name>.enabled=false
  7. Ensure consistency between Ingestion and Augmentation pipelines

    main

    For successful RAG, your query-time augmentation pipeline must be compatible with your ingestion pipeline. If these do not match, retrieval accuracy will fail.

    Requirements for consistency:

    • Embedding Model: The model used for ingestion must be identical to the one used for query-time augmentation.
    • Content Format: Text segments and metadata must match what the retriever expects.
    • Vector Store: The schema and content format must be consistent; changing them requires re-ingesting all documents.
    • Metadata: Any metadata used for ranking or filtering must be consistent with what was stored during ingestion.
  8. Understand Secure MCP Authentication and Permissions

    main

    The Secure MCP implementation uses the Streamable HTTP transport protocol and relies on GitHub OAuth2 for identity.

    Authentication Flow

    1. Client Login: The MCP Client (a Quarkus application) initiates a GitHub OAuth2 authorization code flow.
    2. Token Propagation: The client acquires a GitHub access token and propagates it as a Bearer token in HTTP requests to the MCP server.
    3. Server Validation: The Quarkus MCP server validates the bearer token.

    Authorization and Permissions

    Access to MCP tools is restricted by permissions. Specifically, the MCP server endpoint for tools requires the read:name permission.

    How permissions are granted:

    • The MCP server augments the identity derived from the GitHub bearer token.
    • It checks a database for a record matching the GitHub account name that possesses the read:name permission.
    • If a match is found, the permission is added to the security identity.
  9. Understand the Data Ingestion and RAG processes

    main

    Retrieval Augmented Generation (RAG) in Quarkus LangChain4j is split into two distinct phases:

    1. The Data Ingestion Process: This involves collecting, cleaning, and transforming data (like CSVs or text files) into vectorized documents that are stored in a database (e.g., Redis or Chroma).
    2. The RAG Process: When a user interacts with the LLM, the system seeks relevant documents from the database and passes them to the model to augment its response.

    Embeddings (numerical vectors) are used during the RAG process to efficiently compute the similarity between user queries and stored documents.

  10. Implement output guardrails

    main

    Since LLMs can generate harmful, inappropriate, or incorrectly formatted responses, you should implement guardrails to validate model output before it is used by your application. Common strategies include:

    • Format Validation: Ensure outputs (like JSON) are well-formed and conform to your expected schema.
    • Content Moderation: Use moderation models or keyword filtering to detect harmful or undesirable content.
    • Tool-Use Validation: If the LLM is intended to call tools or functions, validate that the requested tool and its parameters are legitimate and safe to execute.
  11. Configure multiple named PGVector stores

    main

    You can configure multiple named stores, each backed by a different datasource. This is useful for managing embeddings for different domains or tenants in separate databases.

    To configure a named store, use the pattern quarkus.langchain4j.pgvector.<name>.<property>.

    If you only want to use named stores and not the default one, disable the default store using quarkus.langchain4j.pgvector.default-store-enabled=false.

    quarkus.langchain4j.pgvector.products.dimension=1536
    quarkus.langchain4j.pgvector.products.datasource=products-ds
    quarkus.langchain4j.pgvector.products.table=product_embeddings