CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-quarkiverse-langchain4j--quarkus-langchain4j-core-deployment

Quarkus deployment extension for LangChain4j integration providing build-time processing, BuildItem APIs, and configuration for integrating Large Language Models into Quarkus applications

Overview
Eval results
Files

index.mddocs/

Quarkus LangChain4j Core Deployment Extension

Package Overview

The quarkus-langchain4j-core-deployment module is a Quarkus deployment extension that provides build-time processing for LangChain4j integration. This module runs exclusively at build time and enables other Quarkus extensions to integrate LangChain4j capabilities into their applications.

Package: io.quarkiverse.langchain4j.deployment Type: Quarkus Deployment Extension Language: Java (Maven) Group ID: io.quarkiverse.langchain4j Artifact ID: quarkus-langchain4j-core-deployment Version: 1.7.4

Maven Dependency

To use this deployment extension in your Quarkus extension, add the following dependency:

<dependency>
    <groupId>io.quarkiverse.langchain4j</groupId>
    <artifactId>quarkus-langchain4j-core-deployment</artifactId>
    <version>1.7.4</version>
</dependency>

Purpose

This deployment module enables Quarkus extensions to:

  • Register AI model providers (chat, embedding, image, moderation, scoring models)
  • Configure AI services declaratively using @RegisterAiService
  • Discover and register tools for AI agents
  • Configure build-time behavior for LangChain4j components
  • Integrate with Quarkus DevServices for local model inference
  • Process guardrails for input/output validation
  • Configure chat memory providers
  • Enable observability (metrics and tracing) for AI services

Core Concepts

Quarkus Build-Time Architecture

Quarkus follows a build-time/runtime split architecture:

  • Build Time: Code analysis, configuration resolution, bytecode generation, native image preparation
  • Runtime: Optimized application execution with pre-computed metadata

This deployment module runs at build time and uses the following key abstractions:

BuildItem

BuildItems are data carriers used in the Quarkus build step chain. They are the primary API for communication between extensions during the build process.

  • MultiBuildItem: Multiple instances can be produced (e.g., multiple model providers)
  • SimpleBuildItem: Single instance per build (e.g., consolidated metadata)

BuildStep

Methods annotated with @BuildStep that execute during the build process. BuildSteps:

  • Consume BuildItems as method parameters
  • Produce BuildItems via BuildProducer<T> parameters
  • Execute in dependency order based on BuildItem consumption/production

BuildProducer

A parameter type used in BuildStep methods to produce BuildItems:

@BuildStep
void myBuildStep(BuildProducer<MyBuildItem> producer) {
    producer.produce(new MyBuildItem(...));
}

BuildConsumer

Implicitly used when a BuildStep method accepts a BuildItem as a parameter:

@BuildStep
void myBuildStep(MyBuildItem item) {
    // Consume the BuildItem
}

Basic Usage Example

Here's a simple processor that registers a custom chat model provider:

package com.example.deployment;

import io.quarkiverse.langchain4j.deployment.items.ChatModelProviderCandidateBuildItem;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;

public class MyModelProcessor {

    @BuildStep
    public void registerChatModelProvider(
            BuildProducer<ChatModelProviderCandidateBuildItem> chatModelProvider) {

        // Register "my-provider" as a candidate chat model provider
        chatModelProvider.produce(
            new ChatModelProviderCandidateBuildItem("my-provider")
        );
    }
}

Architecture Overview

The deployment extension follows a multi-phase build process:

  1. Discovery Phase: Extensions register model provider candidates
  2. Selection Phase: Core module selects providers based on configuration
  3. Bean Creation Phase: CDI beans are synthesized for selected providers
  4. AI Service Phase: AI services are created with tools and guardrails
  5. DevServices Phase: Optional local inference servers are started (dev/test mode)

Core Import Classes

// BuildItem base classes
import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.builder.item.SimpleBuildItem;

// Build step annotations
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.annotations.ExecutionTime;

// Configuration
import io.quarkiverse.langchain4j.deployment.config.LangChain4jBuildConfig;

// Common BuildItems
import io.quarkiverse.langchain4j.deployment.items.ChatModelProviderCandidateBuildItem;
import io.quarkiverse.langchain4j.deployment.items.SelectedChatModelProviderBuildItem;
import io.quarkiverse.langchain4j.deployment.DeclarativeAiServiceBuildItem;

// Utility classes
import io.quarkiverse.langchain4j.deployment.DotNames;
import io.quarkiverse.langchain4j.deployment.LangChain4jDotNames;

API Categories

The deployment extension provides 73 public API elements organized into the following categories:

1. BuildItems (37 classes)

BuildItems are the primary extension API. See BuildItems Documentation for complete details.

Key BuildItems:

  • Model Providers: Register and select model providers
    • ChatModelProviderCandidateBuildItem - Register chat model provider
    • SelectedChatModelProviderBuildItem - Access selected provider
    • Similar items for embedding, image, moderation, and scoring models

Example: Registering a model provider

@BuildStep
void registerProvider(BuildProducer<ChatModelProviderCandidateBuildItem> producer) {
    producer.produce(new ChatModelProviderCandidateBuildItem("openai"));
}
  • AI Services: Configure declarative AI services
    • DeclarativeAiServiceBuildItem - AI service metadata from @RegisterAiService

Example: Consuming AI service metadata

@BuildStep
void processAiServices(List<DeclarativeAiServiceBuildItem> aiServices) {
    for (DeclarativeAiServiceBuildItem service : aiServices) {
        String modelName = service.getChatModelName();
        // Process service configuration
    }
}
  • Tools: Tool discovery and metadata

    • ToolMethodBuildItem - Methods annotated with @Tool
    • ToolsMetadataBuildItem - Consolidated tool metadata
  • Behavior Customization: Control extension behavior

    • RequestChatModelBeanBuildItem - Force bean creation
    • AnnotationsImpliesAiServiceBuildItem - Custom AI service detection
    • SkipOutputFormatInstructionsBuildItem - Control output formatting

See BuildItems Documentation for all 37 BuildItem classes.

2. Processors (12 classes)

Processors contain @BuildStep methods that execute during the build. See Processors Documentation.

Key Processors:

  • AiServicesProcessor - Main AI service registration
  • BeansProcessor - Model provider selection and bean creation
  • ToolProcessor - Tool discovery and validation
  • ChatMemoryProcessor - Chat memory provider setup
  • InProcessEmbeddingProcessor - Local embedding models

See Processors Documentation for all processors and build step patterns.

3. Configuration (7 classes)

Build-time configuration classes using SmallRye Config. See Configuration Documentation.

Root Configuration:

@ConfigRoot(phase = BUILD_TIME)
@ConfigMapping(prefix = "quarkus.langchain4j")
public interface LangChain4jBuildConfig {
    BaseConfig defaultConfig();
    Map<String, BaseConfig> namedConfig();
    DevServicesConfig devservices();
    boolean responseSchema();
}

Example: Accessing configuration in a BuildStep

@BuildStep
void useConfig(LangChain4jBuildConfig config) {
    boolean devServicesEnabled = config.devservices().enabled();
    String provider = config.defaultConfig().chatModel().provider().orElse("default");
}

See Configuration Documentation for all configuration classes.

4. Utilities (8 classes)

Utility classes for common tasks. See Utilities Documentation.

Key Utilities:

  • DotNames - Constants for common Java types (50+ DotName constants)
  • LangChain4jDotNames - Constants for LangChain4j types (100+ constants)
  • TemplateUtil - Template parsing and validation
  • MethodUtil - Method signature utilities
  • HashUtil - SHA-1 hashing

Example: Using DotNames

import io.quarkiverse.langchain4j.deployment.DotNames;
import io.quarkiverse.langchain4j.deployment.LangChain4jDotNames;

// Check if a type is a String
if (DotNames.STRING.equals(methodParameter.type().name())) {
    // Handle string parameter
}

// Check if a method is annotated with @Tool
if (method.hasAnnotation(LangChain4jDotNames.TOOL)) {
    // Process tool method
}

See Utilities Documentation for all utility classes.

Extension Points

Extensions can integrate with this deployment module by:

Producing BuildItems

Register new capabilities:

@BuildStep
void registerCapabilities(
        BuildProducer<ChatModelProviderCandidateBuildItem> chatProvider,
        BuildProducer<EmbeddingModelProviderCandidateBuildItem> embeddingProvider) {

    // Register as a chat model provider
    chatProvider.produce(new ChatModelProviderCandidateBuildItem("my-provider"));

    // Register as an embedding model provider
    embeddingProvider.produce(new EmbeddingModelProviderCandidateBuildItem("my-provider"));
}

Consuming BuildItems

React to configuration decisions:

@BuildStep
void reactToSelection(List<SelectedChatModelProviderBuildItem> selected) {
    for (SelectedChatModelProviderBuildItem item : selected) {
        if ("my-provider".equals(item.getProvider())) {
            String configName = item.getConfigName();
            // Create beans for this configuration
        }
    }
}

Customizing Behavior

Control how AI services behave:

@BuildStep
void customizeBehavior(
        BuildProducer<AnnotationsImpliesAiServiceBuildItem> annotations,
        BuildProducer<SkipOutputFormatInstructionsBuildItem> skipFormat) {

    // Make @MyAnnotation imply AI service
    annotations.produce(new AnnotationsImpliesAiServiceBuildItem(
        Set.of(DotName.createSimple("com.example.MyAnnotation"))
    ));

    // Skip output format for certain methods
    skipFormat.produce(new SkipOutputFormatInstructionsBuildItem(
        method -> method.hasAnnotation(DotName.createSimple("com.example.NoFormat"))
    ));
}

Build Step Execution Order

BuildSteps execute in an order determined by their BuildItem dependencies. The core execution flow is:

  1. Provider Registration: Extensions register provider candidates
  2. Configuration Loading: Build-time configuration is resolved
  3. Provider Selection: Core selects providers based on config
  4. Bean Synthesis: CDI beans are created for selected providers
  5. AI Service Discovery: @RegisterAiService interfaces are processed
  6. Tool Discovery: @Tool methods are discovered
  7. Guardrail Processing: Input/output guardrails are configured
  8. DevServices: Local inference servers are started (dev/test only)

Common Patterns

Pattern 1: Conditional BuildStep

Only run when a capability is present:

@BuildStep(onlyIf = MyCondition.class)
void conditionalStep() {
    // Only runs if MyCondition.getAsBoolean() returns true
}

Pattern 2: Recording Runtime Values

Pass build-time decisions to runtime:

@BuildStep
@Record(ExecutionTime.STATIC_INIT)
void recordValues(MyRecorder recorder, List<SelectedChatModelProviderBuildItem> selected) {
    for (SelectedChatModelProviderBuildItem item : selected) {
        recorder.recordProvider(item.getProvider(), item.getConfigName());
    }
}

Pattern 3: Consuming Multiple BuildItems

@BuildStep
void combineData(
        List<DeclarativeAiServiceBuildItem> aiServices,
        List<ToolMethodBuildItem> tools,
        ToolsMetadataBuildItem metadata) {

    // Combine multiple sources of information
    Map<String, List<ToolMethodCreateInfo>> toolsByService = metadata.getMetadata();

    for (DeclarativeAiServiceBuildItem service : aiServices) {
        String serviceName = service.getServiceClassInfo().name().toString();
        List<ToolMethodCreateInfo> servicTools = toolsByService.get(serviceName);
        // Process combined data
    }
}

Next Steps

Key Notes

  • This is a deployment-time module - all classes run at build time only
  • BuildItems are the primary API for extension communication
  • Use BuildProducer<T> to produce BuildItems, method parameters to consume them
  • Configuration is resolved at build time via @ConfigRoot and @ConfigMapping
  • The module follows Quarkus conventions for native image optimization
  • DevServices-related BuildSteps use @BuildSteps(onlyIfNot = IsNormal.class) to run only in dev/test mode

Install with Tessl CLI

npx tessl i tessl/maven-io-quarkiverse-langchain4j--quarkus-langchain4j-core-deployment@1.7.0

docs

build-items.md

configuration.md

index.md

processors.md

utilities.md

tile.json