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

utilities.mddocs/

Utilities API Reference

This document covers utility classes, interfaces, and enums that support the deployment extension's functionality.

Utility Classes

DotNames

Package: io.quarkiverse.langchain4j.deployment

Constants for common Java types as Jandex DotName instances. Use these when working with Jandex's IndexView to check types, annotations, or method signatures.

public class DotNames {
    // Primitive types
    public static final DotName VOID;
    public static final DotName BOOLEAN;
    public static final DotName PRIMITIVE_BOOLEAN;
    public static final DotName BYTE;
    public static final DotName PRIMITIVE_BYTE;
    public static final DotName CHARACTER;
    public static final DotName PRIMITIVE_CHAR;
    public static final DotName DOUBLE;
    public static final DotName PRIMITIVE_DOUBLE;
    public static final DotName FLOAT;
    public static final DotName PRIMITIVE_FLOAT;
    public static final DotName INTEGER;
    public static final DotName PRIMITIVE_INT;
    public static final DotName LONG;
    public static final DotName PRIMITIVE_LONG;
    public static final DotName SHORT;
    public static final DotName PRIMITIVE_SHORT;

    // Numeric types
    public static final DotName BIG_INTEGER;
    public static final DotName BIG_DECIMAL;

    // Common types
    public static final DotName STRING;
    public static final DotName URI;
    public static final DotName URL;
    public static final DotName LIST;
    public static final DotName SET;
    public static final DotName OBJECT;
    public static final DotName OBJECT_ARRAY;
    public static final DotName RECORD;

    // Date/Time types
    public static final DotName INSTANT;
    public static final DotName LOCAL_DATE;
    public static final DotName LOCAL_DATE_TIME;
    public static final DotName LOCAL_TIME;
    public static final DotName OFFSET_DATE_TIME;
    public static final DotName OFFSET_TIME;
    public static final DotName YEAR;
    public static final DotName YEAR_MONTH;

    // Reactive types
    public static final DotName MULTI;
    public static final DotName UNI;
    public static final DotName COMPLETION_STAGE;

    // Threading annotations
    public static final DotName BLOCKING;
    public static final DotName NON_BLOCKING;
    public static final DotName RUN_ON_VIRTUAL_THREAD;

    // CDI types
    public static final DotName CDI_INSTANCE;
    public static final DotName EXECUTOR;

    // Exception types
    public static final DotName THROWABLE;
    public static final DotName EXCEPTION;

    // LangChain4j types
    public static final DotName CHAT_MODEL_LISTENER;
    public static final DotName MODEL_AUTH_PROVIDER;
    public static final DotName TOOL;
    public static final DotName OUTPUT_GUARDRAIL_ACCUMULATOR;
    public static final DotName AI_RESPONSE_AUGMENTER;           // The AiResponseAugmenter interface
    public static final DotName RESPONSE_AUGMENTER_ANNOTATION;   // The @ResponseAugmenter annotation

    // REST Client
    public static final DotName REGISTER_REST_CLIENT;
}

Usage Example:

import io.quarkiverse.langchain4j.deployment.DotNames;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.Type;

// Check if a method returns a String
if (DotNames.STRING.equals(method.returnType().name())) {
    // Handle string return type
}

// Check if a parameter is a List
Type paramType = method.parameterType(0);
if (DotNames.LIST.equals(paramType.name())) {
    // Handle List parameter
}

// Check if a method returns Uni (reactive)
if (DotNames.UNI.equals(method.returnType().name())) {
    // Handle reactive return type
}

// Check for blocking annotation
if (method.hasAnnotation(DotNames.BLOCKING)) {
    // Method is marked as blocking
}

LangChain4jDotNames

Package: io.quarkiverse.langchain4j.deployment

Constants for LangChain4j-specific types and annotations. Contains 100+ DotName constants for LangChain4j classes.

public class LangChain4jDotNames {
    // Model interfaces
    public static final DotName CHAT_MODEL;
    public static final DotName STREAMING_CHAT_MODEL;
    public static final DotName SCORING_MODEL;
    public static final DotName EMBEDDING_MODEL;
    public static final DotName MODERATION_MODEL;
    public static final DotName IMAGE_MODEL;

    // Message types
    public static final DotName CHAT_MESSAGE;
    public static final DotName AI_MESSAGE;
    public static final DotName TOKEN_STREAM;

    // Annotations
    public static final DotName REGISTER_AI_SERVICES;
    public static final DotName SYSTEM_MESSAGE;
    public static final DotName USER_MESSAGE;
    public static final DotName MODEL_NAME;
    public static final DotName V; // Template variable

    // Guardrails
    public static final DotName INPUT_GUARDRAILS;
    public static final DotName OUTPUT_GUARDRAILS;
    public static final DotName TOOL_INPUT_GUARDRAILS;
    public static final DotName TOOL_OUTPUT_GUARDRAILS;
    public static final DotName TOOL_INPUT_GUARDRAIL;
    public static final DotName TOOL_OUTPUT_GUARDRAIL;

    // Memory
    public static final DotName CHAT_MEMORY_PROVIDER;
    public static final DotName SEED_MEMORY;
    public static final DotName MEMORY_ID;

    // RAG
    public static final DotName RETRIEVER;
    public static final DotName RETRIEVAL_AUGMENTOR;

    // Tools
    public static final DotName TOOL_PROVIDER;

    // Special supplier classes from RegisterAiService
    static final DotName BEAN_CHAT_MODEL_SUPPLIER;
    static final DotName BEAN_STREAMING_CHAT_MODEL_SUPPLIER;
    static final DotName BEAN_CHAT_MEMORY_PROVIDER_SUPPLIER;
    static final DotName NO_CHAT_MEMORY_PROVIDER_SUPPLIER;
    static final DotName BEAN_IF_EXISTS_RETRIEVAL_AUGMENTOR_SUPPLIER;
    static final DotName NO_RETRIEVAL_AUGMENTOR_SUPPLIER;
    static final DotName BEAN_IF_EXISTS_MODERATION_MODEL_SUPPLIER;
    static final DotName BEAN_IF_EXISTS_IMAGE_MODEL_SUPPLIER;
    static final DotName BEAN_IF_EXISTS_TOOL_PROVIDER_SUPPLIER;
    static final DotName NO_TOOL_PROVIDER_SUPPLIER;

    // Media types
    static final DotName IMAGE;
    static final DotName AUDIO;
    static final DotName VIDEO;
    static final DotName PDF_FILE;

    // URL annotations
    static final DotName IMAGE_URL;
    static final DotName AUDIO_URL;
    static final DotName VIDEO_URL;
    static final DotName PDF_URL;

    // Error handling
    static final DotName HANDLE_TOOL_ARGUMENT_ERROR;
    static final DotName HANDLE_TOOL_EXECUTION_ERROR;

    // Additional types (100+ total constants)
    // ...
}

Usage Example:

import io.quarkiverse.langchain4j.deployment.LangChain4jDotNames;
import org.jboss.jandex.*;

// Check if a class implements ChatModel
ClassInfo classInfo = index.getClassByName(someDotName);
if (classInfo.interfaceNames().contains(LangChain4jDotNames.CHAT_MODEL)) {
    // This is a ChatModel implementation
}

// Find all @RegisterAiService annotations
Collection<AnnotationInstance> annotations =
    index.getAnnotations(LangChain4jDotNames.REGISTER_AI_SERVICES);

for (AnnotationInstance annotation : annotations) {
    ClassInfo serviceClass = annotation.target().asClass();
    // Process AI service
}

// Check if a method has @SystemMessage
MethodInfo method = ...;
if (method.hasAnnotation(LangChain4jDotNames.SYSTEM_MESSAGE)) {
    AnnotationInstance systemMessage =
        method.annotation(LangChain4jDotNames.SYSTEM_MESSAGE);
    // Extract system message template
}

// Check if a parameter uses @V annotation
for (AnnotationInstance annotation : method.annotations()) {
    if (annotation.name().equals(LangChain4jDotNames.V)) {
        // This parameter is a template variable
    }
}

TemplateUtil

Package: io.quarkiverse.langchain4j.deployment

Utilities for parsing and validating prompt templates.

public class TemplateUtil {

    /**
     * Extracts template from @SystemMessage or @UserMessage annotation.
     * Handles both inline templates and templates loaded from resources.
     *
     * @param instance AnnotationInstance of SystemMessage or UserMessage
     * @return Template string, or empty string if not specified
     */
    public static String getTemplateFromAnnotationInstance(
        AnnotationInstance instance);
}

Usage Example:

import io.quarkiverse.langchain4j.deployment.TemplateUtil;
import org.jboss.jandex.AnnotationInstance;

// Extract template from annotation
AnnotationInstance systemMessage =
    method.annotation(LangChain4jDotNames.SYSTEM_MESSAGE);

String template = TemplateUtil.getTemplateFromAnnotationInstance(systemMessage);
// Returns: "You are a helpful assistant. User context: {{context}}"

// Parse template to find variables
List<List<Expression.Part>> parts = TemplateUtil.parts(template);
for (List<Expression.Part> part : parts) {
    // Each part represents a {{variable}} in the template
    String variableName = part.get(0).getName();
    // Validate that method has parameter matching variable name
}

Template Loading: Templates can be specified inline or loaded from resources:

// Inline template
@SystemMessage("You are a {{role}} assistant")

// From resource file
@SystemMessage(fromResource = "prompts/system-message.txt")

getTemplateFromAnnotationInstance() handles both cases automatically.

MethodUtil

Package: io.quarkiverse.langchain4j.deployment

Utilities for working with method signatures.

public final class MethodUtil {

    /**
     * Returns the signature of a method as a string.
     * Format: methodName(type1, type2, ...)
     *
     * @param method The method to get signature from
     * @return Method signature string
     */
    public static String signature(MethodInfo method);

    /**
     * Checks if signatures of two methods match.
     * Compares method name and parameter types.
     *
     * @param a First method
     * @param b Second method
     * @return true if signatures match, false otherwise
     */
    public static boolean methodSignaturesMatch(MethodInfo a, MethodInfo b);
}

Usage Example:

import io.quarkiverse.langchain4j.deployment.MethodUtil;
import org.jboss.jandex.MethodInfo;

// Get method signature for error messages
MethodInfo method = ...;
String sig = MethodUtil.signature(method);
// Returns: "processRequest(java.lang.String, int)"

throw new IllegalStateException(
    "Invalid method signature: " + sig
);

// Check if two methods have the same signature
MethodInfo interfaceMethod = ...;
MethodInfo implementationMethod = ...;

if (!MethodUtil.methodSignaturesMatch(interfaceMethod, implementationMethod)) {
    throw new IllegalStateException(
        "Method signatures don't match: " +
        MethodUtil.signature(interfaceMethod) + " vs " +
        MethodUtil.signature(implementationMethod)
    );
}

HashUtil

Package: io.quarkiverse.langchain4j.deployment

SHA-1 hashing utilities.

public class HashUtil {

    /**
     * Computes SHA-1 hash of a string.
     *
     * @param value String to hash
     * @return Hex-encoded SHA-1 hash
     */
    public static String sha1(String value);

    /**
     * Computes SHA-1 hash of byte array.
     *
     * @param value Bytes to hash
     * @return Hex-encoded SHA-1 hash
     */
    public static String sha1(byte[] value);
}

Usage Example:

import io.quarkiverse.langchain4j.deployment.HashUtil;

// Generate unique identifier for a configuration
String configKey = "provider=" + provider + ",model=" + model;
String configId = HashUtil.sha1(configKey);
// Returns: "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"

// Use hash as bean name suffix to ensure uniqueness
String beanName = "chatModel_" + HashUtil.sha1(configName);

JarResourceUtil

Package: io.quarkiverse.langchain4j.deployment

Utilities for working with JAR file resources.

public class JarResourceUtil {

    /**
     * Finds JAR entries matching a predicate.
     *
     * @param jarPath Path to JAR file
     * @param entryPredicate Predicate to test each entry
     * @return List of matching JAR entries
     */
    public static List<JarEntry> matchingJarEntries(
        Path jarPath,
        Predicate<JarEntry> entryPredicate);

    /**
     * Determines the JAR file location for a class.
     *
     * @param classFromJar Any class from the JAR
     * @return Path to the JAR file
     * @throws IllegalStateException if JAR location cannot be determined
     */
    public static Path determineJarLocation(Class<?> classFromJar);
}

Usage Example:

import io.quarkiverse.langchain4j.deployment.JarResourceUtil;
import java.nio.file.Path;
import java.util.List;
import java.util.jar.JarEntry;

// Find all .bin files in a JAR (e.g., OpenNLP models)
Path jarPath = JarResourceUtil.determineJarLocation(OpenNlpTokenizer.class);

List<JarEntry> binFiles = JarResourceUtil.matchingJarEntries(
    jarPath,
    entry -> entry.getName().endsWith(".bin")
);

for (JarEntry entry : binFiles) {
    // Register as native resource
    nativeResources.produce(
        new NativeImageResourceBuildItem(entry.getName())
    );
}

// Find ONNX model files
List<JarEntry> onnxModels = JarResourceUtil.matchingJarEntries(
    jarPath,
    entry -> entry.getName().endsWith(".onnx")
);

Interfaces

ProviderHolder

Package: io.quarkiverse.langchain4j.deployment.items

Marker interface for BuildItems that hold provider information.

public interface ProviderHolder {
    /**
     * Gets the provider name.
     *
     * @return Provider identifier (e.g., "openai", "ollama")
     */
    String getProvider();
}

Implemented By:

  • ChatModelProviderCandidateBuildItem
  • EmbeddingModelProviderCandidateBuildItem
  • ImageModelProviderCandidateBuildItem
  • ModerationModelProviderCandidateBuildItem
  • ScoringModelProviderCandidateBuildItem
  • InProcessEmbeddingBuildItem

Usage Example:

@BuildStep
void processProviders(List<ProviderHolder> allProviders) {
    Set<String> providerNames = allProviders.stream()
        .map(ProviderHolder::getProvider)
        .collect(Collectors.toSet());

    // Check if a specific provider is registered
    if (providerNames.contains("openai")) {
        // OpenAI provider is available
    }
}

DevServicesModelRequired

Package: io.quarkiverse.langchain4j.deployment.items

Interface for BuildItems representing DevServices model requirements.

public interface DevServicesModelRequired {
    /**
     * Gets the provider name.
     *
     * @return Provider identifier
     */
    String getProvider();

    /**
     * Gets the model name to pull in DevServices.
     *
     * @return Model name (e.g., "llama3.2", "phi3")
     */
    String getModelName();

    /**
     * Gets the configuration property for the base URL.
     *
     * @return Property key to configure with DevServices URL
     */
    String getBaseUrlProperty();
}

Implemented By:

  • DevServicesChatModelRequiredBuildItem
  • DevServicesEmbeddingModelRequiredBuildItem

Usage Example:

@BuildStep
@Record(ExecutionTime.STATIC_INIT)
DevServicesResultBuildItem startDevServices(
        List<DevServicesModelRequired> modelRequests,
        DevServicesRecorder recorder) {

    if (modelRequests.isEmpty()) {
        return null;
    }

    // Start Ollama container
    String containerUrl = startOllamaContainer();

    // Configure each provider's base URL
    for (DevServicesModelRequired request : modelRequests) {
        String property = request.getBaseUrlProperty();
        String modelName = request.getModelName();

        // Set config property
        ConfigProviderResolver.instance()
            .getConfig()
            .getConfigValue(property)
            .withValue(containerUrl);

        // Pull model
        pullModel(modelName);
    }

    return new DevServicesResultBuildItem(...);
}

ToolQualifierProvider

Package: io.quarkiverse.langchain4j.deployment.items

Interface for determining CDI qualifiers for tool classes.

public interface ToolQualifierProvider {

    /**
     * Checks if this provider supports the given class.
     *
     * @param classInfo Class to check
     * @return true if this provider handles this class
     */
    boolean supports(ClassInfo classInfo);

    /**
     * Gets the CDI qualifier annotation for this class.
     *
     * @param classInfo Class to get qualifier for
     * @return AnnotationLiteral representing the qualifier
     */
    AnnotationLiteral<?> qualifier(ClassInfo classInfo);

    /**
     * Nested BuildItem wrapper for the provider.
     */
    final class BuildItem extends MultiBuildItem {
        public BuildItem(ToolQualifierProvider provider);
        public ToolQualifierProvider getProvider();
    }
}

Usage Example:

import io.quarkiverse.langchain4j.deployment.items.ToolQualifierProvider;
import org.jboss.jandex.*;
import jakarta.enterprise.util.AnnotationLiteral;

// Implement custom qualifier provider
public class MyToolQualifierProvider implements ToolQualifierProvider {

    @Override
    public boolean supports(ClassInfo classInfo) {
        // Check if class has @MyToolAnnotation
        return classInfo.hasAnnotation(
            DotName.createSimple("com.example.MyToolAnnotation")
        );
    }

    @Override
    public AnnotationLiteral<?> qualifier(ClassInfo classInfo) {
        // Return @MyQualifier annotation as AnnotationLiteral
        return new AnnotationLiteral<com.example.MyQualifier>() {};
    }
}

// Register in a BuildStep
@BuildStep
void registerToolQualifier(
        BuildProducer<ToolQualifierProvider.BuildItem> producer) {
    producer.produce(new ToolQualifierProvider.BuildItem(
        new MyToolQualifierProvider()
    ));
}

OllamaClient

Package: io.quarkiverse.langchain4j.deployment.devservice

Client interface for Ollama server interactions (used by DevServices).

public interface OllamaClient {

    /**
     * Checks if Ollama server is running.
     *
     * @return true if server is available
     */
    boolean isRunning();

    /**
     * Lists models available locally.
     *
     * @return List of ModelInfo for local models
     */
    List<ModelInfo> localModels();

    /**
     * Gets detailed information about a model.
     *
     * @param modelName Model to query
     * @return Model information
     * @throws ModelNotFoundException if model not found
     */
    ModelInfo modelInfo(String modelName);

    /**
     * Pulls a model asynchronously.
     *
     * @param modelName Model to pull
     * @return Flow.Publisher of pull progress lines
     */
    java.util.concurrent.Flow.Publisher<PullAsyncLine> pullAsync(String modelName);

    /**
     * Preloads a chat model into memory.
     *
     * @param modelName Model to preload
     */
    void preloadChatModel(String modelName);

    /**
     * Creates an OllamaClient instance.
     *
     * @param options Client configuration options
     * @return OllamaClient instance
     */
    static OllamaClient create(Options options);

    // Nested classes
    record ModelInfo(
        String name,
        @com.fasterxml.jackson.annotation.JsonProperty("modelfile") String modelFile,
        String parameters,
        Details details
    ) {
        public record Details(String family, String parameterSize) { }
    }

    record PullAsyncLine(String status, Long total, Long completed);

    record Options(String host, int port);

    // Exceptions
    class ModelNotFoundException extends RuntimeException {
        public ModelNotFoundException(String model);
    }
    class ModelDoesNotExistException extends RuntimeException {
        public ModelDoesNotExistException(String model);
    }
    class ServerUnavailableException extends RuntimeException {
        public ServerUnavailableException(String host, int port);
    }
}

Usage Example (typically used internally by DevServicesOllamaProcessor):

import io.quarkiverse.langchain4j.deployment.devservice.OllamaClient;
import java.util.concurrent.Flow;

// Create client (host and port)
OllamaClient client = OllamaClient.create(
    new OllamaClient.Options("localhost", 11434)
);

// Check if server is running
if (client.isRunning()) {
    // Pull a model asynchronously
    Flow.Publisher<OllamaClient.PullAsyncLine> publisher = client.pullAsync("llama3.2");
    publisher.subscribe(new Flow.Subscriber<>() {
        @Override
        public void onNext(OllamaClient.PullAsyncLine line) {
            System.out.println("Progress: " + line.completed() + "/" + line.total());
        }
        // ... other methods
    });

    // Preload for faster responses
    client.preloadChatModel("llama3.2");

    // List available models
    List<OllamaClient.ModelInfo> models = client.localModels();
    models.forEach(model -> System.out.println("Model: " + model.name()));
}

JdkOllamaClient

Package: io.quarkiverse.langchain4j.deployment.devservice

Default implementation of OllamaClient using JDK HTTP client.

public class JdkOllamaClient implements OllamaClient {

    /**
     * Creates client with specified host and port.
     *
     * @param options Connection options (host and port)
     */
    public JdkOllamaClient(Options options);

    // Implements all OllamaClient interface methods
}

Usage:

import io.quarkiverse.langchain4j.deployment.devservice.JdkOllamaClient;
import io.quarkiverse.langchain4j.deployment.devservice.OllamaClient;

// Create client directly
JdkOllamaClient client = new JdkOllamaClient(
    new OllamaClient.Options("localhost", 11434)
);

// Or use factory method
OllamaClient client2 = OllamaClient.create(
    new OllamaClient.Options("localhost", 11434)
);

Langchain4jDevServicesEnabled

Package: io.quarkiverse.langchain4j.deployment.devservice

Boolean supplier that determines if LangChain4j DevServices should be enabled. Used as a condition for build steps.

public class Langchain4jDevServicesEnabled implements BooleanSupplier {

    /**
     * Checks if DevServices should be enabled.
     *
     * @return true if DevServices should run
     */
    public boolean getAsBoolean();
}

Usage:

import io.quarkiverse.langchain4j.deployment.devservice.Langchain4jDevServicesEnabled;
import io.quarkus.deployment.annotations.BuildStep;

// Use as condition for build step
@BuildStep(onlyIf = Langchain4jDevServicesEnabled.class)
void maybeStartDevServices() {
    // This only runs when DevServices is enabled
}

Enums

MethodParameterAsTemplateVariableAllowance

Package: io.quarkiverse.langchain4j.deployment

Enumeration for determining how method parameters are included as template variables.

public enum MethodParameterAsTemplateVariableAllowance {
    /**
     * Ignore this parameter - don't include in template variables.
     */
    IGNORE,

    /**
     * Force this parameter to be included in template variables,
     * even if it wouldn't normally be.
     */
    FORCE_ALLOW,

    /**
     * Optionally deny this parameter from template variables.
     */
    OPTIONAL_DENY
}

Usage Example:

import io.quarkiverse.langchain4j.deployment.MethodParameterAsTemplateVariableAllowance;

MethodParameterAsTemplateVariableAllowance determineAllowance(
        MethodParameterInfo param) {

    // Parameters annotated with @MemoryId should be ignored
    if (param.hasAnnotation(LangChain4jDotNames.MEMORY_ID)) {
        return MethodParameterAsTemplateVariableAllowance.IGNORE;
    }

    // Parameters annotated with @V should be forced
    if (param.hasAnnotation(LangChain4jDotNames.V)) {
        return MethodParameterAsTemplateVariableAllowance.FORCE_ALLOW;
    }

    return MethodParameterAsTemplateVariableAllowance.OPTIONAL_DENY;
}

Data Classes (Dev UI)

These classes carry metadata to the Dev UI.

AiServiceInfo

Package: io.quarkiverse.langchain4j.deployment.devui

AI service metadata for Dev UI display.

public class AiServiceInfo {

    public AiServiceInfo(String clazz, List<String> tools);

    /**
     * Gets the AI service class name.
     *
     * @return Fully qualified class name
     */
    public String getClazz();

    /**
     * Gets the list of tools used by this service.
     *
     * @return List of tool class names (fully qualified)
     */
    public List<String> getTools();
}

ToolMethodInfo

Package: io.quarkiverse.langchain4j.deployment.devui

Tool method metadata for Dev UI display.

public class ToolMethodInfo {

    /**
     * Gets the declaring class name.
     *
     * @return Class containing the tool method
     */
    public String getClassName();

    /**
     * Gets the method name.
     *
     * @return Tool method name
     */
    public String getName();

    /**
     * Gets the tool description.
     *
     * @return Description from @Tool annotation
     */
    public String getDescription();
}

ToolProviderInfo

Package: io.quarkiverse.langchain4j.deployment.devui

Tool provider metadata for Dev UI display.

public class ToolProviderInfo {

    /**
     * Gets the provider class name.
     *
     * @return Fully qualified class name
     */
    public String getClassName();

    /**
     * Gets the associated AI service name.
     *
     * @return AI service using this provider
     */
    public String getAiServiceName();

    // Setters for building info
    public void setClassName(String className);
    public void setAiServiceName(String aiServiceName);
}

Usage Example:

@BuildStep
void buildDevUiData(
        List<DeclarativeAiServiceBuildItem> aiServices,
        List<ToolMethodBuildItem> tools,
        BuildProducer<ToolProviderMetaBuildItem> producer) {

    List<ToolProviderInfo> providers = new ArrayList<>();

    for (DeclarativeAiServiceBuildItem service : aiServices) {
        ToolProviderInfo info = new ToolProviderInfo();
        info.setClassName(service.getServiceClassInfo().name().toString());
        info.setAiServiceName(service.getBeanName().orElse("default"));
        providers.add(info);
    }

    producer.produce(new ToolProviderMetaBuildItem(providers));
}

Common Usage Patterns

Pattern: Type Checking with DotNames

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

// Check return type
Type returnType = method.returnType();
if (DotNames.STRING.equals(returnType.name())) {
    // String return type
} else if (DotNames.UNI.equals(returnType.name())) {
    // Reactive Uni return type
} else if (LangChain4jDotNames.TOKEN_STREAM.equals(returnType.name())) {
    // Streaming response
}

// Check parameter types
for (Type paramType : method.parameterTypes()) {
    if (DotNames.LIST.equals(paramType.name())) {
        // List parameter
    } else if (LangChain4jDotNames.CHAT_MESSAGE.equals(paramType.name())) {
        // ChatMessage parameter
    }
}

Pattern: Template Processing

// Extract and validate template
AnnotationInstance userMessage =
    method.annotation(LangChain4jDotNames.USER_MESSAGE);

String template = TemplateUtil.getTemplateFromAnnotationInstance(userMessage);

// Parse template variables
List<List<Expression.Part>> parts = TemplateUtil.parts(template);

Set<String> templateVars = parts.stream()
    .flatMap(List::stream)
    .map(Expression.Part::getName)
    .collect(Collectors.toSet());

// Validate method parameters match template variables
Set<String> methodParams = method.parameters().stream()
    .map(param -> param.name())
    .collect(Collectors.toSet());

if (!methodParams.containsAll(templateVars)) {
    throw new IllegalStateException(
        "Template variables don't match method parameters for " +
        MethodUtil.signature(method)
    );
}

Pattern: JAR Resource Discovery

// Find model files in JAR
Path jarPath = JarResourceUtil.determineJarLocation(MyModel.class);

List<JarEntry> modelFiles = JarResourceUtil.matchingJarEntries(
    jarPath,
    entry -> !entry.isDirectory() &&
             (entry.getName().endsWith(".onnx") ||
              entry.getName().endsWith(".bin"))
);

// Register for native image
for (JarEntry entry : modelFiles) {
    nativeResources.produce(
        new NativeImageResourceBuildItem(entry.getName())
    );
}

Install with Tessl CLI

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

docs

build-items.md

configuration.md

index.md

processors.md

utilities.md

tile.json