LangChain4j integration library for Hugging Face inference capabilities including chat, language, and embedding models
Service Provider Interface (SPI) for customizing model builders and client implementations.
SPI provides extension points through Java's ServiceLoader mechanism, allowing custom implementations of:
Package: dev.langchain4j.model.huggingface.spi
package dev.langchain4j.model.huggingface.spi;
public interface HuggingFaceEmbeddingModelBuilderFactory
extends java.util.function.Supplier<HuggingFaceEmbeddingModel.HuggingFaceEmbeddingModelBuilder> {
HuggingFaceEmbeddingModel.HuggingFaceEmbeddingModelBuilder get();
}Purpose: Provide custom embedding model builders with pre-configured defaults.
@Deprecated(forRemoval = true, since = "1.7.0-beta13")
public interface HuggingFaceChatModelBuilderFactory
extends java.util.function.Supplier<HuggingFaceChatModel.Builder> {
HuggingFaceChatModel.Builder get();
}@Deprecated(forRemoval = true, since = "1.7.0-beta13")
public interface HuggingFaceLanguageModelBuilderFactory
extends java.util.function.Supplier<HuggingFaceLanguageModel.Builder> {
HuggingFaceLanguageModel.Builder get();
}public interface HuggingFaceClientFactory {
HuggingFaceClient create(Input input);
interface Input {
default String baseUrl() { return null; }
String apiKey();
String modelId();
java.time.Duration timeout();
}
}Purpose: Provide custom HTTP client implementations.
package com.example.custom;
import dev.langchain4j.model.huggingface.HuggingFaceEmbeddingModel;
import dev.langchain4j.model.huggingface.spi.HuggingFaceEmbeddingModelBuilderFactory;
import java.time.Duration;
public class CustomEmbeddingBuilderFactory
implements HuggingFaceEmbeddingModelBuilderFactory {
@Override
public HuggingFaceEmbeddingModel.HuggingFaceEmbeddingModelBuilder get() {
return new CustomBuilder();
}
static class CustomBuilder
extends HuggingFaceEmbeddingModel.HuggingFaceEmbeddingModelBuilder {
public CustomBuilder() {
super();
// Set custom defaults
this.timeout(Duration.ofSeconds(60));
this.waitForModel(true);
this.modelId("sentence-transformers/all-MiniLM-L6-v2");
}
}
}package com.example.test;
import dev.langchain4j.model.huggingface.client.*;
import dev.langchain4j.model.huggingface.spi.HuggingFaceClientFactory;
import java.util.List;
import java.util.stream.Collectors;
public class MockClientFactory implements HuggingFaceClientFactory {
@Override
public HuggingFaceClient create(Input input) {
return new MockClient();
}
static class MockClient implements HuggingFaceClient {
@Override
public TextGenerationResponse chat(TextGenerationRequest request) {
return new TextGenerationResponse("Mock chat response");
}
@Override
public TextGenerationResponse generate(TextGenerationRequest request) {
return new TextGenerationResponse("Mock generated text");
}
@Override
public List<float[]> embed(EmbeddingRequest request) {
return request.getInputs().stream()
.map(text -> new float[384]) // Mock 384-dim vectors
.collect(Collectors.toList());
}
}
}package com.example.logging;
import dev.langchain4j.model.huggingface.client.*;
import dev.langchain4j.model.huggingface.spi.HuggingFaceClientFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoggingClientFactory implements HuggingFaceClientFactory {
@Override
public HuggingFaceClient create(Input input) {
HuggingFaceClient delegate = createDefaultClient(input);
return new LoggingClient(delegate);
}
static class LoggingClient implements HuggingFaceClient {
private static final Logger log = LoggerFactory.getLogger(LoggingClient.class);
private final HuggingFaceClient delegate;
LoggingClient(HuggingFaceClient delegate) {
this.delegate = delegate;
}
@Override
public TextGenerationResponse chat(TextGenerationRequest request) {
log.info("Chat request: {}", request.getInputs());
try {
TextGenerationResponse response = delegate.chat(request);
log.info("Chat response: {}", response.getGeneratedText());
return response;
} catch (Exception e) {
log.error("Chat failed", e);
throw e;
}
}
@Override
public TextGenerationResponse generate(TextGenerationRequest request) {
log.info("Generate request: {}", request.getInputs());
try {
TextGenerationResponse response = delegate.generate(request);
log.info("Generated: {}", response.getGeneratedText());
return response;
} catch (Exception e) {
log.error("Generate failed", e);
throw e;
}
}
@Override
public List<float[]> embed(EmbeddingRequest request) {
log.info("Embed request: {} texts", request.getInputs().size());
try {
List<float[]> embeddings = delegate.embed(request);
log.info("Generated {} embeddings", embeddings.size());
return embeddings;
} catch (Exception e) {
log.error("Embed failed", e);
throw e;
}
}
}
private static HuggingFaceClient createDefaultClient(Input input) {
// Create default client implementation
return new DefaultHuggingFaceClient(/* ... */);
}
}package com.example.retry;
import dev.langchain4j.model.huggingface.client.*;
import dev.langchain4j.model.huggingface.spi.HuggingFaceClientFactory;
public class RetryClientFactory implements HuggingFaceClientFactory {
@Override
public HuggingFaceClient create(Input input) {
HuggingFaceClient delegate = createDefaultClient(input);
return new RetryClient(delegate, 3);
}
static class RetryClient implements HuggingFaceClient {
private final HuggingFaceClient delegate;
private final int maxRetries;
RetryClient(HuggingFaceClient delegate, int maxRetries) {
this.delegate = delegate;
this.maxRetries = maxRetries;
}
@Override
public List<float[]> embed(EmbeddingRequest request) {
int attempt = 0;
while (attempt < maxRetries) {
try {
return delegate.embed(request);
} catch (RuntimeException e) {
attempt++;
if (attempt >= maxRetries ||
!isRetryable(e)) {
throw e;
}
sleep((long) Math.pow(2, attempt) * 1000);
}
}
throw new RuntimeException("Max retries exceeded");
}
// Similar implementations for chat() and generate()
private boolean isRetryable(RuntimeException e) {
String msg = e.getMessage();
return msg.contains("429") ||
msg.contains("503") ||
msg.toLowerCase().contains("timeout");
}
private void sleep(long ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}To register SPI implementations, create files in META-INF/services/:
src/main/resources/
└── META-INF/
└── services/
├── dev.langchain4j.model.huggingface.spi.HuggingFaceClientFactory
├── dev.langchain4j.model.huggingface.spi.HuggingFaceEmbeddingModelBuilderFactory
├── dev.langchain4j.model.huggingface.spi.HuggingFaceChatModelBuilderFactory
└── dev.langchain4j.model.huggingface.spi.HuggingFaceLanguageModelBuilderFactoryExample: HuggingFaceClientFactory
com.example.custom.CustomClientFactoryExample: HuggingFaceEmbeddingModelBuilderFactory
com.example.custom.CustomEmbeddingBuilderFactoryEnsure files are included in your JAR:
src/main/resources/ are automatically includedWhen you call builder(), the library searches for SPI implementations:
// From HuggingFaceEmbeddingModel
public static HuggingFaceEmbeddingModelBuilder builder() {
for (HuggingFaceEmbeddingModelBuilderFactory factory :
loadFactories(HuggingFaceEmbeddingModelBuilderFactory.class)) {
return factory.get(); // Use first found
}
return new HuggingFaceEmbeddingModelBuilder(); // Default fallback
}Priority: First implementation found is used.
@Test
public void testCustomBuilder() {
// Assumes CustomBuilderFactory is registered
HuggingFaceEmbeddingModel model = HuggingFaceEmbeddingModel.builder()
.accessToken("test-key")
.build();
// Custom defaults should be applied
assertNotNull(model);
}@Test
public void testMockClient() {
// Assumes MockClientFactory is registered
HuggingFaceEmbeddingModel model = HuggingFaceEmbeddingModel.builder()
.accessToken("test-key")
.build();
// Should use mock client
Embedding emb = model.embed("test").content();
assertNotNull(emb);
assertEquals(384, emb.dimension());
}import java.util.ServiceLoader;
import dev.langchain4j.model.huggingface.spi.HuggingFaceClientFactory;
ServiceLoader<HuggingFaceClientFactory> loader =
ServiceLoader.load(HuggingFaceClientFactory.class);
for (HuggingFaceClientFactory factory : loader) {
System.out.println("Found factory: " + factory.getClass().getName());
}jar tf your-library.jar | grep META-INF/servicesInstall with Tessl CLI
npx tessl i tessl/maven-dev-langchain4j--langchain4j-hugging-face@1.11.0