CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-dev-langchain4j--langchain4j-vertex-ai

LangChain4j integration for Google Vertex AI models including chat, language, embedding, image, and scoring capabilities

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

spi.mddocs/advanced/

Service Provider Interfaces (SPI)

SPI factory interfaces for dependency injection frameworks and custom builder implementations. Enables integration with Spring, Quarkus, and custom DI systems.

Imports

import dev.langchain4j.model.vertexai.spi.VertexAiChatModelBuilderFactory;
import dev.langchain4j.model.vertexai.spi.VertexAiEmbeddingModelBuilderFactory;
import dev.langchain4j.model.vertexai.spi.VertexAiLanguageModelBuilderFactory;
import dev.langchain4j.model.vertexai.spi.VertexAiImageModelBuilderFactory;
import java.util.function.Supplier;

Available SPI Interfaces

public interface VertexAiChatModelBuilderFactory extends Supplier<VertexAiChatModel.Builder> {
    VertexAiChatModel.Builder get();
}

public interface VertexAiEmbeddingModelBuilderFactory extends Supplier<VertexAiEmbeddingModel.Builder> {
    VertexAiEmbeddingModel.Builder get();
}

public interface VertexAiLanguageModelBuilderFactory extends Supplier<VertexAiLanguageModel.Builder> {
    VertexAiLanguageModel.Builder get();
}

public interface VertexAiImageModelBuilderFactory extends Supplier<VertexAiImageModel.Builder> {
    VertexAiImageModel.Builder get();
}

Note: VertexAiScoringModel does not have an SPI factory interface.

How SPI Works

Model classes use Java's ServiceLoader mechanism:

  1. Call builder() on model class
  2. ServiceLoader searches for factory implementations
  3. If found, uses factory's get() method for pre-configured builder
  4. Otherwise, creates default builder

Implementing Custom Factory

1. Implement Interface

package com.example.config;

import dev.langchain4j.model.vertexai.VertexAiChatModel;
import dev.langchain4j.model.vertexai.spi.VertexAiChatModelBuilderFactory;

public class CustomChatModelBuilderFactory implements VertexAiChatModelBuilderFactory {
    @Override
    public VertexAiChatModel.Builder get() {
        return VertexAiChatModel.builder()
            .endpoint("https://us-central1-aiplatform.googleapis.com/v1/")
            .project(System.getenv("GCP_PROJECT_ID"))
            .location("us-central1")
            .publisher("google")
            .maxRetries(5);
    }
}

2. Register Factory

Create file: META-INF/services/dev.langchain4j.model.vertexai.spi.VertexAiChatModelBuilderFactory

Content:

com.example.config.CustomChatModelBuilderFactory

3. Use Factory

// builder() automatically uses your factory
VertexAiChatModel model = VertexAiChatModel.builder()
    .modelName("chat-bison@001")  // Add model-specific config
    .temperature(0.7)
    .build();

Spring Framework Integration

@Configuration
public class VertexAiConfig {

    @Bean
    public VertexAiChatModelBuilderFactory chatModelBuilderFactory(
            @Value("${gcp.project-id}") String projectId,
            @Value("${gcp.location}") String location) {
        return () -> VertexAiChatModel.builder()
            .endpoint("https://" + location + "-aiplatform.googleapis.com/v1/")
            .project(projectId)
            .location(location)
            .publisher("google")
            .maxRetries(3);
    }
}

Quarkus Integration

@ApplicationScoped
public class VertexAiProducer {

    @ConfigProperty(name = "gcp.project-id")
    String projectId;

    @ConfigProperty(name = "gcp.location")
    String location;

    @Produces
    public VertexAiChatModelBuilderFactory chatModelBuilderFactory() {
        return () -> VertexAiChatModel.builder()
            .endpoint("https://" + location + "-aiplatform.googleapis.com/v1/")
            .project(projectId)
            .location(location)
            .publisher("google");
    }
}

Use Cases

Centralized Configuration

public class CentralConfigFactory implements VertexAiChatModelBuilderFactory {
    private static final String PROJECT_ID = loadFromConfig("project.id");
    private static final String LOCATION = loadFromConfig("location");

    @Override
    public VertexAiChatModel.Builder get() {
        return VertexAiChatModel.builder()
            .endpoint(buildEndpoint(LOCATION))
            .project(PROJECT_ID)
            .location(LOCATION)
            .publisher("google")
            .maxRetries(3)
            .credentials(loadCredentials());
    }
}

Environment-Specific Configuration

public class EnvironmentAwareBuilderFactory implements VertexAiChatModelBuilderFactory {
    @Override
    public VertexAiChatModel.Builder get() {
        String env = System.getenv("ENVIRONMENT");

        return switch (env) {
            case "production" -> productionBuilder();
            case "staging" -> stagingBuilder();
            default -> developmentBuilder();
        };
    }

    private VertexAiChatModel.Builder productionBuilder() {
        return VertexAiChatModel.builder()
            .endpoint("https://us-central1-aiplatform.googleapis.com/v1/")
            .project("prod-project-id")
            .location("us-central1")
            .maxRetries(5);
    }

    private VertexAiChatModel.Builder stagingBuilder() {
        return VertexAiChatModel.builder()
            .endpoint("https://us-central1-aiplatform.googleapis.com/v1/")
            .project("staging-project-id")
            .location("us-central1")
            .maxRetries(3);
    }

    private VertexAiChatModel.Builder developmentBuilder() {
        return VertexAiChatModel.builder()
            .endpoint("http://localhost:8080/mock-vertex-ai")
            .project("dev-project")
            .location("us-central1")
            .maxRetries(1);
    }
}

Testing with Mock Builders

public class TestChatModelBuilderFactory implements VertexAiChatModelBuilderFactory {
    @Override
    public VertexAiChatModel.Builder get() {
        return VertexAiChatModel.builder()
            .endpoint("http://localhost:8080/mock-vertex-ai")
            .project("test-project")
            .location("us-central1")
            .publisher("google")
            .maxRetries(1);
    }
}

Multiple Factory Implementations

Example with all model types:

Chat Model Factory

File: META-INF/services/dev.langchain4j.model.vertexai.spi.VertexAiChatModelBuilderFactory

com.example.config.CustomChatModelBuilderFactory

Embedding Model Factory

File: META-INF/services/dev.langchain4j.model.vertexai.spi.VertexAiEmbeddingModelBuilderFactory

com.example.config.CustomEmbeddingModelBuilderFactory

Language Model Factory

File: META-INF/services/dev.langchain4j.model.vertexai.spi.VertexAiLanguageModelBuilderFactory

com.example.config.CustomLanguageModelBuilderFactory

Image Model Factory

File: META-INF/services/dev.langchain4j.model.vertexai.spi.VertexAiImageModelBuilderFactory

com.example.config.CustomImageModelBuilderFactory

Implementation Example

package com.example.config;

import dev.langchain4j.model.vertexai.VertexAiEmbeddingModel;
import dev.langchain4j.model.vertexai.spi.VertexAiEmbeddingModelBuilderFactory;

public class CustomEmbeddingModelBuilderFactory implements VertexAiEmbeddingModelBuilderFactory {
    @Override
    public VertexAiEmbeddingModel.Builder get() {
        return VertexAiEmbeddingModel.builder()
            .endpoint("us-central1-aiplatform.googleapis.com:443")
            .project(System.getenv("GCP_PROJECT_ID"))
            .location("us-central1")
            .publisher("google")
            .maxRetries(3)
            .maxSegmentsPerBatch(100);
    }
}

Package Location

All SPI interfaces located in:

dev.langchain4j.model.vertexai.spi

Benefits

  1. Dependency Injection: Seamless DI framework integration
  2. Centralized Configuration: Default settings in one place
  3. Testability: Easy implementation swapping for tests
  4. Flexibility: Customize builder creation without code changes
  5. Environment Management: Different configs per environment
  6. Credential Management: Centralize credential loading

Important Notes

  • Multiple factory implementations can exist on classpath
  • First factory found by ServiceLoader is used
  • If no factory found, default builder is used
  • Each model type has independent factory interface
  • VertexAiScoringModel has no factory interface
  • Factories discovered at runtime via standard SPI mechanism

Debugging SPI

Check if factories are loaded:

import java.util.ServiceLoader;

ServiceLoader<VertexAiChatModelBuilderFactory> loader =
    ServiceLoader.load(VertexAiChatModelBuilderFactory.class);

for (VertexAiChatModelBuilderFactory factory : loader) {
    System.out.println("Found factory: " + factory.getClass().getName());
}

Common Issues

Factory Not Found

Issue: Custom factory not being used

Solutions:

  1. Verify META-INF/services/ file exists in classpath
  2. Check file name matches fully qualified interface name
  3. Verify factory class is in compiled JAR/classpath
  4. Check for typos in factory class name in services file

Multiple Factories Conflict

Issue: Multiple factories on classpath

Behavior: First one found by ServiceLoader is used (order undefined)

Solution: Remove conflicting factories or use explicit ordering mechanism

Install with Tessl CLI

npx tessl i tessl/maven-dev-langchain4j--langchain4j-vertex-ai@1.11.0

docs

advanced

spi.md

index.md

quick-reference.md

tile.json