8.5 KiB
8.5 KiB
LangChain4j Spring Boot Integration - API References
Complete API reference for Spring Boot integration with LangChain4j.
Spring Boot Starter Dependencies
Maven
<!-- Core Spring Boot LangChain4j integration -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>0.27.0</version>
</dependency>
<!-- OpenAI integration -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
<version>0.27.0</version>
</dependency>
Gradle
implementation 'dev.langchain4j:langchain4j-spring-boot-starter:0.27.0'
implementation 'dev.langchain4j:langchain4j-open-ai-spring-boot-starter:0.27.0'
Auto-Configuration Properties
OpenAI Configuration
langchain4j:
open-ai:
api-key: ${OPENAI_API_KEY}
model-name: gpt-4o-mini
temperature: 0.7
top-p: 1.0
max-tokens: 2000
timeout: 60s
log-requests: true
log-responses: true
openai-embedding:
api-key: ${OPENAI_API_KEY}
model-name: text-embedding-3-small
timeout: 60s
Vector Store Configuration
langchain4j:
vector-store:
type: in-memory # or pinecone, weaviate, qdrant, etc.
# Pinecone
pinecone:
api-key: ${PINECONE_API_KEY}
index-name: my-index
namespace: production
# Qdrant
qdrant:
host: localhost
port: 6333
collection-name: documents
# Weaviate
weaviate:
host: localhost
port: 8080
collection-name: Documents
Spring Configuration Annotations
@Configuration
@Configuration
public class AiConfig {
@Bean
public ChatModel chatModel() {
// Bean definition
}
@Bean
@ConditionalOnMissingBean
public EmbeddingModel embeddingModel() {
// Fallback bean
}
}
@ConditionalOnProperty
@Configuration
@ConditionalOnProperty(
prefix = "app.ai",
name = "enabled",
havingValue = "true"
)
public class AiFeatureConfig {
// Configuration only if enabled
}
@EnableConfigurationProperties
@Configuration
@EnableConfigurationProperties(AiProperties.class)
public class AiConfig {
@Autowired
private AiProperties aiProperties;
}
Dependency Injection
Constructor Injection (Recommended)
@Service
public class ChatService {
private final ChatModel chatModel;
private final EmbeddingModel embeddingModel;
public ChatService(ChatModel chatModel, EmbeddingModel embeddingModel) {
this.chatModel = chatModel;
this.embeddingModel = embeddingModel;
}
}
Field Injection (Discouraged)
@Service
public class ChatService {
@Autowired
private ChatModel chatModel; // Not recommended
}
Setter Injection
@Service
public class ChatService {
private ChatModel chatModel;
@Autowired
public void setChatModel(ChatModel chatModel) {
this.chatModel = chatModel;
}
}
REST Annotations
@RestController with RequestMapping
@RestController
@RequestMapping("/api/chat")
public class ChatController {
@PostMapping
public ResponseEntity<Response> chat(@RequestBody ChatRequest request) {
// Implementation
}
@GetMapping("/{id}")
public ResponseEntity<Response> getChat(@PathVariable String id) {
// Implementation
}
}
RequestBody Validation
@PostMapping
public ResponseEntity<Response> chat(@Valid @RequestBody ChatRequest request) {
// Validates request object
}
public class ChatRequest {
@NotBlank(message = "Message cannot be blank")
private String message;
@Min(0)
@Max(100)
private int maxTokens = 2000;
}
Exception Handling
@ControllerAdvice
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<ErrorResponse> handleBadRequest(IllegalArgumentException e) {
return ResponseEntity.badRequest()
.body(new ErrorResponse(400, e.getMessage()));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGlobalException(Exception e) {
return ResponseEntity.internalServerError()
.body(new ErrorResponse(500, "Internal server error"));
}
}
ResponseStatusException
if (!authorized) {
throw new ResponseStatusException(
HttpStatus.FORBIDDEN,
"User not authorized"
);
}
Async and Reactive
@Async
@Service
@EnableAsync
public class AsyncService {
@Async
public CompletableFuture<String> processAsync(String input) {
String result = processSync(input);
return CompletableFuture.completedFuture(result);
}
}
@Scheduled
@Component
public class ScheduledTasks {
@Scheduled(fixedRate = 60000) // Every minute
public void performTask() {
// Task implementation
}
@Scheduled(cron = "0 0 * * * *") // Daily at midnight
public void dailyTask() {
// Daily task
}
}
Testing
@SpringBootTest
@SpringBootTest
class ChatServiceTest {
@Autowired
private ChatService chatService;
@Test
void testChat() {
// Test implementation
}
}
@WebMvcTest
@WebMvcTest(ChatController.class)
class ChatControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ChatService chatService;
@Test
void testChatEndpoint() throws Exception {
mockMvc.perform(post("/api/chat")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"message\": \"Hello\"}"))
.andExpect(status().isOk());
}
}
@DataJpaTest
@DataJpaTest
class DocumentRepositoryTest {
@Autowired
private DocumentRepository repository;
@Test
void testFindByUserId() {
// Test implementation
}
}
Logging Configuration
application.yml
logging:
level:
root: INFO
dev.langchain4j: DEBUG
org.springframework: WARN
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n"
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file:
name: logs/app.log
Health Checks
Custom Health Indicator
@Component
public class AiHealthIndicator extends AbstractHealthIndicator {
@Override
protected void doHealthCheck(Health.Builder builder) {
try {
// Check AI service availability
chatModel.chat("ping");
builder.up();
} catch (Exception e) {
builder.down().withDetail("reason", e.getMessage());
}
}
}
Actuator Integration
Maven Dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Configuration
management:
endpoints:
web:
exposure:
include: health, metrics, info
endpoint:
health:
show-details: always
Security Configuration
@EnableWebSecurity
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/private/**").authenticated()
.and()
.httpBasic();
return http.build();
}
}
Bean Lifecycle
@PostConstruct and @PreDestroy
@Service
public class AiService {
@PostConstruct
public void init() {
// Initialize resources
embeddingStore = createEmbeddingStore();
}
@PreDestroy
public void cleanup() {
// Clean up resources
embeddingStore.close();
}
}
Best Practices
- Use Constructor Injection: Explicitly declare dependencies
- Externalize Configuration: Use application.yml for settings
- Handle Exceptions: Use @ControllerAdvice for consistent error handling
- Implement Caching: Cache AI responses when appropriate
- Use Async Processing: For long-running AI operations
- Add Health Checks: Implement custom health indicators
- Log Appropriately: Debug AI service calls in development
- Test Thoroughly: Use @SpringBootTest and @WebMvcTest
- Secure APIs: Implement authentication and authorization
- Monitor Performance: Track AI service metrics