1 框架介绍
1.1 LangChain4j概述
01.框架简介
a.核心特性
a.功能说明
LangChain4j是LangChain的Java实现,为Java生态提供LLM应用开发能力。完全支持Java类型系统和企业级开发规范。与Spring Boot深度集成,适合企业级应用。LangChain4j是Java开发者构建AI应用的首选框架。
b.代码示例
---
// 1. LangChain4j基础示例
// Maven依赖
/*
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>0.27.1</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>0.27.1</version>
</dependency>
*/
// 2. 简单调用
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
public class QuickStart {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-3.5-turbo")
.build();
String response = model.generate("你好,世界!");
System.out.println(response);
}
}
// 3. 链式调用
import dev.langchain4j.chain.ConversationalChain;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
public class ChainExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
ConversationalChain chain = ConversationalChain.builder()
.chatLanguageModel(model)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.build();
String response1 = chain.execute("我叫张三");
System.out.println(response1);
String response2 = chain.execute("我叫什么名字?");
System.out.println(response2); // "你叫张三"
}
}
// 4. 模块化架构
/*
LangChain4j模块:
- langchain4j-core:核心抽象和接口
- langchain4j-open-ai:OpenAI集成
- langchain4j-hugging-face:HuggingFace集成
- langchain4j-embeddings:嵌入模型
- langchain4j-document-parsers:文档解析
- langchain4j-spring-boot-starter:Spring Boot集成
*/
// 5. 类型安全
import dev.langchain4j.service.AiServices;
interface Assistant {
String chat(String message);
}
public class TypeSafeExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 声明式接口
Assistant assistant = AiServices.create(Assistant.class, model);
String response = assistant.chat("你好");
System.out.println(response);
}
}
// 6. 流式输出
import dev.langchain4j.model.StreamingResponseHandler;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
public class StreamingExample {
public static void main(String[] args) {
var model = OpenAiStreamingChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
model.generate("讲个故事", new StreamingResponseHandler<String>() {
@Override
public void onNext(String token) {
System.out.print(token);
}
@Override
public void onComplete(String fullResponse) {
System.out.println("\n完成");
}
@Override
public void onError(Throwable error) {
System.err.println("错误: " + error.getMessage());
}
});
}
}
// 7. 与Python版本对比
// Python LangChain
// from langchain.chat_models import ChatOpenAI
// llm = ChatOpenAI()
// response = llm.invoke("Hello")
// Java LangChain4j
ChatLanguageModel llm = OpenAiChatModel.builder()
.apiKey(apiKey)
.build();
String response = llm.generate("Hello");
// API设计理念相同,但遵循Java命名约定
// 8. 依赖注入支持
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class ChatService {
private final ChatLanguageModel model;
@Autowired
public ChatService(ChatLanguageModel model) {
this.model = model;
}
public String chat(String message) {
return model.generate(message);
}
}
// 9. 异步支持
import java.util.concurrent.CompletableFuture;
public class AsyncExample {
public CompletableFuture<String> chatAsync(String message) {
return CompletableFuture.supplyAsync(() -> {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
return model.generate(message);
});
}
}
// 使用
AsyncExample example = new AsyncExample();
example.chatAsync("你好")
.thenAccept(response -> System.out.println(response))
.exceptionally(error -> {
System.err.println("错误: " + error.getMessage());
return null;
});
// 10. 配置管理
import dev.langchain4j.model.openai.OpenAiChatModelName;
public class ConfigExample {
public static ChatLanguageModel createModel() {
return OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(OpenAiChatModelName.GPT_3_5_TURBO)
.temperature(0.7)
.maxTokens(1000)
.timeout(Duration.ofSeconds(30))
.maxRetries(3)
.logRequests(true)
.logResponses(true)
.build();
}
}
System.out.println("✓ LangChain4j概述完成");
---
b.应用场景
a.功能说明
LangChain4j适用于企业级AI应用开发。支持知识库问答、智能客服、文档分析等场景。与Java企业技术栈无缝集成。适合需要类型安全和高性能的场景。
b.代码示例
---
// 1. 企业知识库场景
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
public class KnowledgeBaseApp {
private EmbeddingStore<TextSegment> embeddingStore;
private ChatLanguageModel model;
public void initialize() {
// 初始化模型
model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 初始化向量存储
embeddingStore = new InMemoryEmbeddingStore<>();
// 加载企业文档
List<Document> documents = loadDocuments();
// 向量化并存储
// ... 实现细节
}
public String query(String question) {
// 检索相关文档
// 生成答案
return model.generate(question);
}
}
// 2. 智能客服场景
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
interface CustomerServiceAgent {
@SystemMessage("你是一个专业的客服助手")
String handleCustomerQuery(@UserMessage String query);
}
public class CustomerServiceApp {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
CustomerServiceAgent agent = AiServices.create(
CustomerServiceAgent.class,
model
);
String response = agent.handleCustomerQuery("如何退货?");
System.out.println(response);
}
}
// 3. Spring Boot应用场景
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
@SpringBootApplication
@RestController
@RequestMapping("/api")
public class LangChain4jApplication {
private final ChatLanguageModel model;
public LangChain4jApplication(ChatLanguageModel model) {
this.model = model;
}
@PostMapping("/chat")
public ChatResponse chat(@RequestBody ChatRequest request) {
String response = model.generate(request.getMessage());
return new ChatResponse(response);
}
public static void main(String[] args) {
SpringApplication.run(LangChain4jApplication.class, args);
}
}
// 4. 微服务集成场景
@Service
public class AIService {
private final ChatLanguageModel model;
private final EmbeddingStore<TextSegment> store;
@Autowired
public AIService(
ChatLanguageModel model,
EmbeddingStore<TextSegment> store
) {
this.model = model;
this.store = store;
}
public String processRequest(String input) {
// 业务逻辑
return model.generate(input);
}
}
System.out.println("✓ 应用场景示例完成");
---
1.2 Java生态集成
01.Spring集成
a.Spring Boot自动配置
a.功能说明
LangChain4j提供Spring Boot Starter实现自动配置。通过application.yml配置模型参数。支持依赖注入和Bean管理。Spring集成简化企业级开发。
b.代码示例
---
// 1. Maven依赖
/*
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>0.27.1</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
<version>0.27.1</version>
</dependency>
*/
// 2. application.yml配置
/*
langchain4j:
open-ai:
chat-model:
api-key: ${OPENAI_API_KEY}
model-name: gpt-3.5-turbo
temperature: 0.7
max-tokens: 1000
timeout: 30s
max-retries: 3
log-requests: true
log-responses: true
*/
// 3. 自动注入
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import dev.langchain4j.model.chat.ChatLanguageModel;
@Service
public class ChatService {
private final ChatLanguageModel model;
@Autowired
public ChatService(ChatLanguageModel model) {
this.model = model;
}
public String chat(String message) {
return model.generate(message);
}
}
// 4. REST Controller
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/chat")
public class ChatController {
private final ChatService chatService;
@Autowired
public ChatController(ChatService chatService) {
this.chatService = chatService;
}
@PostMapping
public ChatResponse chat(@RequestBody ChatRequest request) {
String response = chatService.chat(request.getMessage());
return new ChatResponse(response);
}
}
// 5. 配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
@Configuration
public class LangChain4jConfig {
@Bean
public EmbeddingModel embeddingModel() {
return OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("text-embedding-ada-002")
.build();
}
@Bean
public EmbeddingStore<TextSegment> embeddingStore() {
return new InMemoryEmbeddingStore<>();
}
}
// 6. 启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LangChain4jApplication {
public static void main(String[] args) {
SpringApplication.run(LangChain4jApplication.class, args);
}
}
// 7. 属性配置类
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "langchain4j")
public class LangChain4jProperties {
private String apiKey;
private String modelName;
private Double temperature;
private Integer maxTokens;
// Getters and Setters
public String getApiKey() { return apiKey; }
public void setApiKey(String apiKey) { this.apiKey = apiKey; }
public String getModelName() { return modelName; }
public void setModelName(String modelName) { this.modelName = modelName; }
public Double getTemperature() { return temperature; }
public void setTemperature(Double temperature) { this.temperature = temperature; }
public Integer getMaxTokens() { return maxTokens; }
public void setMaxTokens(Integer maxTokens) { this.maxTokens = maxTokens; }
}
System.out.println("✓ Spring Boot集成完成");
---
b.Maven和Gradle
a.功能说明
支持Maven和Gradle两种主流构建工具。管理LangChain4j依赖和版本。配置编译和打包。构建工具管理项目生命周期。
b.代码示例
---
// 1. Maven配置
/*
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>langchain4j-demo</artifactId>
<version>1.0.0</version>
<properties>
<java.version>17</java.version>
<langchain4j.version>0.27.1</langchain4j.version>
</properties>
<dependencies>
<!-- LangChain4j核心 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- OpenAI集成 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- 嵌入模型 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- 文档处理 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-document-parser-apache-pdfbox</artifactId>
<version>${langchain4j.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
*/
// 2. Gradle配置
/*
// build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'com.example'
version = '1.0.0'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'dev.langchain4j:langchain4j:0.27.1'
implementation 'dev.langchain4j:langchain4j-open-ai:0.27.1'
implementation 'dev.langchain4j:langchain4j-embeddings:0.27.1'
implementation 'dev.langchain4j:langchain4j-spring-boot-starter:0.27.1'
// Spring Boot
implementation 'org.springframework.boot:spring-boot-starter-web'
// Test
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
*/
// 3. 依赖管理BOM
/*
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>0.27.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
</dependency>
</dependencies>
*/
// 4. 多模块项目
/*
project-root/
├── pom.xml (父POM)
├── langchain4j-core/
│ └── pom.xml
├── langchain4j-api/
│ └── pom.xml
└── langchain4j-web/
└── pom.xml
父POM:
<modules>
<module>langchain4j-core</module>
<module>langchain4j-api</module>
<module>langchain4j-web</module>
</modules>
*/
System.out.println("✓ 构建工具配置完成");
---
1.3 核心优势
01.企业级特性
a.类型安全
a.功能说明
Java强类型系统确保编译时类型检查。IDE提供完整的代码提示和重构支持。减少运行时错误提升代码质量。类型安全是Java的核心优势。
b.代码示例
---
// 1. 强类型接口
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.SystemMessage;
// 定义类型安全的AI服务接口
interface Translator {
@SystemMessage("你是一个专业翻译")
String translate(@UserMessage("将{text}翻译为{language}") String text, String language);
}
public class TypeSafeExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 编译时类型检查
Translator translator = AiServices.create(Translator.class, model);
// IDE自动提示方法和参数
String result = translator.translate("你好", "英语");
System.out.println(result);
}
}
// 2. 泛型支持
import dev.langchain4j.data.message.AiMessage;
import java.util.List;
public class GenericExample<T> {
private final ChatLanguageModel model;
public GenericExample(ChatLanguageModel model) {
this.model = model;
}
public List<T> process(List<String> inputs, Class<T> resultType) {
// 类型安全的批量处理
return inputs.stream()
.map(input -> model.generate(input))
.map(response -> parseResponse(response, resultType))
.collect(Collectors.toList());
}
private T parseResponse(String response, Class<T> type) {
// 类型转换逻辑
return null; // 示例
}
}
// 3. 结构化输出
import dev.langchain4j.service.Result;
class Person {
private String name;
private int age;
private String occupation;
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getOccupation() { return occupation; }
public void setOccupation(String occupation) { this.occupation = occupation; }
}
interface PersonExtractor {
@UserMessage("从以下文本提取人物信息:{text}")
Person extractPerson(String text);
}
// 使用
PersonExtractor extractor = AiServices.create(PersonExtractor.class, model);
Person person = extractor.extractPerson("张三,25岁,软件工程师");
// 编译时类型安全
System.out.println(person.getName()); // IDE自动提示
// 4. 枚举类型
enum Sentiment {
POSITIVE, NEGATIVE, NEUTRAL
}
interface SentimentAnalyzer {
@UserMessage("分析情感:{text}")
Sentiment analyze(String text);
}
// 返回强类型枚举
SentimentAnalyzer analyzer = AiServices.create(SentimentAnalyzer.class, model);
Sentiment sentiment = analyzer.analyze("今天天气真好!");
if (sentiment == Sentiment.POSITIVE) {
System.out.println("正面情感");
}
// 5. Optional返回值
import java.util.Optional;
interface QuestionAnswerer {
@UserMessage("回答:{question}")
Optional<String> answer(String question);
}
QuestionAnswerer qa = AiServices.create(QuestionAnswerer.class, model);
Optional<String> answer = qa.answer("什么是AI?");
answer.ifPresent(System.out::println);
// 6. 集合类型
interface KeywordExtractor {
@UserMessage("从以下文本提取关键词:{text}")
List<String> extractKeywords(String text);
}
KeywordExtractor extractor = AiServices.create(KeywordExtractor.class, model);
List<String> keywords = extractor.extractKeywords("LangChain4j是Java的AI框架");
keywords.forEach(System.out::println);
System.out.println("✓ 类型安全示例完成");
---
b.性能优化
a.功能说明
Java的JIT编译和内存管理提供优异性能。支持高并发和大规模请求处理。线程池和连接复用优化资源利用。适合高负载的生产环境。
b.代码示例
---
// 1. 并发处理
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.List;
import java.util.ArrayList;
public class ConcurrentProcessing {
private final ChatLanguageModel model;
private final ExecutorService executor;
public ConcurrentProcessing(ChatLanguageModel model, int threads) {
this.model = model;
this.executor = Executors.newFixedThreadPool(threads);
}
public List<String> processBatch(List<String> inputs) throws Exception {
List<Future<String>> futures = new ArrayList<>();
// 提交任务
for (String input : inputs) {
Future<String> future = executor.submit(() ->
model.generate(input)
);
futures.add(future);
}
// 收集结果
List<String> results = new ArrayList<>();
for (Future<String> future : futures) {
results.add(future.get());
}
return results;
}
public void shutdown() {
executor.shutdown();
}
}
// 2. 连接池
import dev.langchain4j.model.chat.ChatLanguageModel;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class ModelPool {
private final BlockingQueue<ChatLanguageModel> pool;
private final int maxSize;
public ModelPool(int maxSize) {
this.maxSize = maxSize;
this.pool = new LinkedBlockingQueue<>(maxSize);
// 预创建模型
for (int i = 0; i < maxSize; i++) {
pool.offer(createModel());
}
}
private ChatLanguageModel createModel() {
return OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
}
public ChatLanguageModel acquire() throws InterruptedException {
return pool.take();
}
public void release(ChatLanguageModel model) {
pool.offer(model);
}
public <T> T use(ModelFunction<T> function) throws Exception {
ChatLanguageModel model = acquire();
try {
return function.apply(model);
} finally {
release(model);
}
}
}
@FunctionalInterface
interface ModelFunction<T> {
T apply(ChatLanguageModel model) throws Exception;
}
// 3. 缓存机制
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
public class CachedModel {
private final ChatLanguageModel model;
private final Map<String, String> cache;
public CachedModel(ChatLanguageModel model) {
this.model = model;
this.cache = new ConcurrentHashMap<>();
}
public String generate(String input) {
return cache.computeIfAbsent(input, key -> {
System.out.println("缓存未命中,调用模型");
return model.generate(key);
});
}
public void clearCache() {
cache.clear();
}
}
System.out.println("✓ 性能优化示例完成");
---
02.企业集成
a.数据库集成
a.功能说明
与JPA、MyBatis等ORM框架集成。支持关系型和NoSQL数据库。实现向量数据持久化。数据库集成满足企业数据管理需求。
b.代码示例
---
// 1. JPA集成
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
@Table(name = "chat_history")
public class ChatMessage {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "user_id")
private String userId;
@Column(name = "role")
private String role; // "user" or "assistant"
@Column(name = "content", columnDefinition = "TEXT")
private String content;
@Column(name = "created_at")
private LocalDateTime createdAt;
// Constructors, Getters, Setters
public ChatMessage() {}
public ChatMessage(String userId, String role, String content) {
this.userId = userId;
this.role = role;
this.content = content;
this.createdAt = LocalDateTime.now();
}
// Getters and Setters omitted for brevity
}
// Repository
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface ChatMessageRepository extends JpaRepository<ChatMessage, Long> {
List<ChatMessage> findByUserIdOrderByCreatedAtAsc(String userId);
}
// Service
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class PersistentChatService {
@Autowired
private ChatMessageRepository repository;
@Autowired
private ChatLanguageModel model;
public String chat(String userId, String message) {
// 保存用户消息
repository.save(new ChatMessage(userId, "user", message));
// 获取历史
List<ChatMessage> history = repository.findByUserIdOrderByCreatedAtAsc(userId);
// 调用模型(包含历史上下文)
String response = model.generate(message);
// 保存AI响应
repository.save(new ChatMessage(userId, "assistant", response));
return response;
}
}
// 2. Redis集成
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class RedisCacheService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private ChatLanguageModel model;
public String getCachedResponse(String query) {
String cacheKey = "llm:response:" + query;
// 检查缓存
String cached = redisTemplate.opsForValue().get(cacheKey);
if (cached != null) {
System.out.println("缓存命中");
return cached;
}
// 调用模型
String response = model.generate(query);
// 存入缓存(1小时)
redisTemplate.opsForValue().set(cacheKey, response, 3600, TimeUnit.SECONDS);
return response;
}
}
System.out.println("✓ 数据库集成示例完成");
---
2 快速开始
2.1 Maven配置
01.项目初始化
a.创建Maven项目
a.功能说明
使用Maven创建LangChain4j项目。配置JDK 17+环境。管理依赖版本和插件。Maven是Java项目的标准构建工具。
b.代码示例
---
// 1. pom.xml基础配置
/*
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>langchain4j-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>LangChain4j Demo</name>
<description>LangChain4j示例项目</description>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<langchain4j.version>0.27.1</langchain4j.version>
</properties>
<dependencies>
<!-- LangChain4j核心 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- OpenAI集成 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
*/
// 2. 完整依赖配置
/*
<dependencies>
<!-- LangChain4j核心 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- OpenAI -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- Embeddings -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- 所有嵌入模型 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-all-minilm-l6-v2</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- 文档解析器 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-document-parser-apache-pdfbox</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-document-parser-apache-poi</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- 向量存储 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-store-pinecone</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- Ollama本地模型 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama</artifactId>
<version>${langchain4j.version}</version>
</dependency>
</dependencies>
*/
// 3. BOM依赖管理
/*
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>0.27.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 使用BOM后,子依赖无需指定版本 -->
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
</dependency>
</dependencies>
*/
// 4. 插件配置
/*
<build>
<plugins>
<!-- 编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- 打包插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.example.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- 测试插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</build>
*/
// 5. Profile配置
/*
<profiles>
<!-- 开发环境 -->
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<env>dev</env>
</properties>
</profile>
<!-- 生产环境 -->
<profile>
<id>prod</id>
<properties>
<env>prod</env>
</properties>
</profile>
</profiles>
*/
// 使用:mvn clean install -Pprod
System.out.println("✓ Maven配置完成");
---
2.2 基础示例
01.第一个程序
a.Hello World
a.功能说明
创建最简单的LangChain4j程序。调用OpenAI模型生成响应。验证环境配置正确。Hello World是学习的第一步。
b.代码示例
---
// 1. 最简单的示例
package com.example;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
public class HelloWorld {
public static void main(String[] args) {
// 创建模型
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-3.5-turbo")
.build();
// 生成响应
String response = model.generate("你好,世界!");
// 打印结果
System.out.println(response);
}
}
// 运行:mvn clean compile exec:java -Dexec.mainClass="com.example.HelloWorld"
// 2. 配置参数
public class ConfiguredExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-3.5-turbo")
.temperature(0.7) // 控制随机性
.maxTokens(1000) // 最大令牌数
.topP(1.0) // 核采样
.frequencyPenalty(0.0) // 频率惩罚
.presencePenalty(0.0) // 存在惩罚
.timeout(Duration.ofSeconds(30)) // 超时
.maxRetries(3) // 重试次数
.logRequests(true) // 记录请求
.logResponses(true) // 记录响应
.build();
String response = model.generate("介绍一下Java");
System.out.println(response);
}
}
// 3. 多轮对话
import dev.langchain4j.chain.ConversationalChain;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
public class ConversationExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 创建对话链,保留10轮历史
ConversationalChain chain = ConversationalChain.builder()
.chatLanguageModel(model)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.build();
// 第一轮
System.out.println("用户: 我叫张三");
String response1 = chain.execute("我叫张三");
System.out.println("AI: " + response1);
// 第二轮
System.out.println("\n用户: 我喜欢编程");
String response2 = chain.execute("我喜欢编程");
System.out.println("AI: " + response2);
// 第三轮(测试记忆)
System.out.println("\n用户: 我叫什么名字?");
String response3 = chain.execute("我叫什么名字?");
System.out.println("AI: " + response3); // 应该记得是"张三"
}
}
// 4. 流式输出
import dev.langchain4j.model.StreamingResponseHandler;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import dev.langchain4j.model.output.Response;
public class StreamingExample {
public static void main(String[] args) throws InterruptedException {
var model = OpenAiStreamingChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-3.5-turbo")
.build();
System.out.print("AI: ");
model.generate("讲一个短故事", new StreamingResponseHandler<String>() {
@Override
public void onNext(String token) {
// 每个token到达时打印
System.out.print(token);
}
@Override
public void onComplete(Response<String> response) {
System.out.println("\n\n✓ 生成完成");
}
@Override
public void onError(Throwable error) {
System.err.println("\n✗ 错误: " + error.getMessage());
}
});
// 等待完成
Thread.sleep(10000);
}
}
// 5. 异常处理
public class ErrorHandlingExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.timeout(Duration.ofSeconds(5))
.maxRetries(2)
.build();
try {
String response = model.generate("你好");
System.out.println("成功: " + response);
} catch (Exception e) {
System.err.println("调用失败: " + e.getMessage());
e.printStackTrace();
}
}
}
// 6. 环境变量配置
public class EnvConfigExample {
public static void main(String[] args) {
// 方式1:从环境变量读取
String apiKey = System.getenv("OPENAI_API_KEY");
// 方式2:从系统属性读取
// String apiKey = System.getProperty("openai.api.key");
// 方式3:从配置文件读取
// Properties props = new Properties();
// props.load(new FileInputStream("config.properties"));
// String apiKey = props.getProperty("openai.api.key");
if (apiKey == null || apiKey.isEmpty()) {
System.err.println("请设置 OPENAI_API_KEY 环境变量");
System.exit(1);
}
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(apiKey)
.build();
String response = model.generate("测试");
System.out.println(response);
}
}
System.out.println("✓ 基础示例完成");
---
2.3 依赖管理
01.版本控制
a.依赖版本管理
a.功能说明
统一管理LangChain4j依赖版本。避免版本冲突和兼容性问题。使用BOM简化版本管理。版本控制确保项目稳定性。
b.代码示例
---
// 1. 使用BOM统一版本
/*
<dependencyManagement>
<dependencies>
<!-- LangChain4j BOM -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>0.27.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Boot BOM(可选) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.2.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 无需指定版本,由BOM管理 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings</artifactId>
</dependency>
</dependencies>
*/
// 2. 属性管理版本
/*
<properties>
<java.version>17</java.version>
<langchain4j.version>0.27.1</langchain4j.version>
<openai.version>0.27.1</openai.version>
<slf4j.version>2.0.9</slf4j.version>
<junit.version>5.10.1</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${openai.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
*/
// 3. 版本范围
/*
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<!-- 接受0.27.x的任意小版本 -->
<version>[0.27.0,0.28.0)</version>
</dependency>
*/
// 4. 排除传递依赖
/*
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain4j.version}</version>
<exclusions>
<!-- 排除冲突的日志依赖 -->
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 使用自己选择的日志实现 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.14</version>
</dependency>
*/
// 5. 依赖范围
/*
<dependencies>
<!-- 编译和运行时需要 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<scope>compile</scope>
</dependency>
<!-- 仅运行时需要 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 仅测试时需要 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<!-- 由容器提供 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
*/
// 6. 可选依赖
/*
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-all-minilm-l6-v2</artifactId>
<optional>true</optional>
</dependency>
*/
// 7. 依赖分析
// 命令:mvn dependency:tree
// 输出依赖树,检查冲突
/*
[INFO] com.example:langchain4j-demo:jar:1.0.0-SNAPSHOT
[INFO] +- dev.langchain4j:langchain4j:jar:0.27.1:compile
[INFO] | +- org.slf4j:slf4j-api:jar:2.0.9:compile
[INFO] | \- com.google.code.gson:gson:jar:2.10.1:compile
[INFO] +- dev.langchain4j:langchain4j-open-ai:jar:0.27.1:compile
[INFO] | \- com.squareup.okhttp3:okhttp:jar:4.12.0:compile
[INFO] \- org.slf4j:slf4j-simple:jar:2.0.9:compile
*/
// 8. 查看有效POM
// 命令:mvn help:effective-pom
// 显示所有继承和导入后的最终POM
System.out.println("✓ 依赖版本管理完成");
---
b.依赖冲突解决
a.功能说明
识别和解决依赖冲突。使用Maven enforcer插件检查。排除冲突的传递依赖。确保依赖兼容性。
b.代码示例
---
// 1. Maven Enforcer插件
/*
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<id>enforce</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<!-- 要求Java版本 -->
<requireJavaVersion>
<version>[17,)</version>
</requireJavaVersion>
<!-- 要求Maven版本 -->
<requireMavenVersion>
<version>[3.8,)</version>
</requireMavenVersion>
<!-- 检查依赖收敛 -->
<dependencyConvergence/>
<!-- 禁止重复依赖 -->
<banDuplicatePomDependencyVersions/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
*/
// 2. 解决版本冲突
/*
<!-- 场景:两个库依赖不同版本的gson -->
<!-- 方式1:显式声明版本 -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<!-- Maven会优先使用显式声明的版本 -->
*/
// 3. 排除冲突依赖
/*
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 使用统一的日志实现 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.14</version>
</dependency>
*/
// 4. 分析冲突
// 命令:mvn dependency:analyze
/*
输出:
[WARNING] Used undeclared dependencies found:
[WARNING] com.google.code.gson:gson:jar:2.10.1:compile
[WARNING] Unused declared dependencies found:
[WARNING] org.slf4j:slf4j-simple:jar:2.0.9:compile
*/
// 5. 复制依赖
// 命令:mvn dependency:copy-dependencies
// 将所有依赖复制到target/dependency/
System.out.println("✓ 依赖冲突解决完成");
---
02.信创适配
a.国产化依赖
a.功能说明
替换为国产化兼容的依赖版本。配置国产Maven镜像仓库。使用Ollama替代OpenAI。确保信创环境兼容性。
b.代码示例
---
// 1. 使用Ollama本地模型
/*
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama</artifactId>
<version>${langchain4j.version}</version>
</dependency>
*/
// Java代码
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.ollama.OllamaChatModel;
public class XinchuangExample {
public static void main(String[] args) {
// 使用本地Ollama模型
ChatLanguageModel model = OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen:7b")
.temperature(0.7)
.build();
String response = model.generate("你好,信创环境!");
System.out.println(response);
}
}
// 2. 配置Maven国内镜像
/*
~/.m2/settings.xml:
<settings>
<mirrors>
<mirror>
<id>aliyun</id>
<mirrorOf>central</mirrorOf>
<name>阿里云Maven镜像</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
<mirror>
<id>huawei</id>
<mirrorOf>central</mirrorOf>
<name>华为云Maven镜像</name>
<url>https://repo.huaweicloud.com/repository/maven/</url>
</mirror>
</mirrors>
</settings>
*/
// 3. 达梦数据库集成
/*
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver18</artifactId>
<version>8.1.2.192</version>
</dependency>
*/
// Spring配置
/*
spring:
datasource:
driver-class-name: dm.jdbc.driver.DmDriver
url: jdbc:dm://localhost:5236/SYSDBA
username: SYSDBA
password: SYSDBA
*/
// 4. 国密算法
/*
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
*/
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.Security;
public class SM4Example {
static {
Security.addProvider(new BouncyCastleProvider());
}
public static String encrypt(String data, String key) {
// SM4加密实现
// ...
return null;
}
}
System.out.println("✓ 信创适配完成");
---
3 核心组件
3.1 ChatLanguageModel
01.模型接口
a.ChatLanguageModel基础
a.功能说明
ChatLanguageModel是LangChain4j的核心接口。封装各种LLM的统一调用方式。支持OpenAI、Ollama等多种模型。统一接口简化模型切换。
b.代码示例
---
// 1. ChatLanguageModel接口定义
package dev.langchain4j.model.chat;
public interface ChatLanguageModel {
// 生成单个响应
String generate(String userMessage);
// 生成多轮对话响应
Response<AiMessage> generate(List<ChatMessage> messages);
// 生成多轮对话响应(带工具调用)
Response<AiMessage> generate(List<ChatMessage> messages, List<ToolSpecification> toolSpecifications);
}
// 2. OpenAI实现
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiChatModelName;
public class OpenAIExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(OpenAiChatModelName.GPT_3_5_TURBO)
.temperature(0.7)
.maxTokens(1000)
.build();
String response = model.generate("介绍一下Java");
System.out.println(response);
}
}
// 3. Ollama实现
import dev.langchain4j.model.ollama.OllamaChatModel;
public class OllamaExample {
public static void main(String[] args) {
ChatLanguageModel model = OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen:7b")
.temperature(0.7)
.build();
String response = model.generate("介绍一下Java");
System.out.println(response);
}
}
// 4. 多轮对话
import dev.langchain4j.data.message.*;
import dev.langchain4j.model.output.Response;
import java.util.List;
import java.util.ArrayList;
public class MultiRoundExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 构建消息列表
List<ChatMessage> messages = new ArrayList<>();
// 系统消息
messages.add(new SystemMessage("你是一个专业的Java导师"));
// 用户消息
messages.add(new UserMessage("什么是泛型?"));
// 调用模型
Response<AiMessage> response = model.generate(messages);
System.out.println(response.content().text());
}
}
// 5. 模型切换
public class ModelSwitcher {
private final ChatLanguageModel model;
public ModelSwitcher(String modelType) {
this.model = createModel(modelType);
}
private ChatLanguageModel createModel(String type) {
switch (type.toLowerCase()) {
case "openai":
return OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
case "ollama":
return OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen:7b")
.build();
default:
throw new IllegalArgumentException("不支持的模型类型: " + type);
}
}
public String chat(String message) {
return model.generate(message);
}
public static void main(String[] args) {
// 使用环境变量切换模型
String modelType = System.getenv("MODEL_TYPE");
if (modelType == null) {
modelType = "ollama"; // 默认使用本地模型
}
ModelSwitcher switcher = new ModelSwitcher(modelType);
String response = switcher.chat("你好");
System.out.println(response);
}
}
// 6. 响应对象
import dev.langchain4j.model.output.TokenUsage;
import dev.langchain4j.model.output.FinishReason;
public class ResponseExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
List<ChatMessage> messages = List.of(
new UserMessage("你好")
);
Response<AiMessage> response = model.generate(messages);
// 获取内容
String content = response.content().text();
System.out.println("内容: " + content);
// 获取token使用情况
TokenUsage tokenUsage = response.tokenUsage();
System.out.println("输入tokens: " + tokenUsage.inputTokenCount());
System.out.println("输出tokens: " + tokenUsage.outputTokenCount());
System.out.println("总tokens: " + tokenUsage.totalTokenCount());
// 获取结束原因
FinishReason finishReason = response.finishReason();
System.out.println("结束原因: " + finishReason);
}
}
System.out.println("✓ ChatLanguageModel基础完成");
---
b.流式模型
a.功能说明
StreamingChatLanguageModel支持流式输出。实时接收模型生成的token。适合长文本生成场景。流式输出提升用户体验。
b.代码示例
---
// 1. 基础流式输出
import dev.langchain4j.model.StreamingResponseHandler;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import dev.langchain4j.model.output.Response;
public class StreamingExample {
public static void main(String[] args) throws InterruptedException {
var model = OpenAiStreamingChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-3.5-turbo")
.build();
System.out.print("AI: ");
model.generate("写一首关于春天的诗", new StreamingResponseHandler<String>() {
@Override
public void onNext(String token) {
System.out.print(token);
}
@Override
public void onComplete(Response<String> response) {
System.out.println("\n\n✓ 完成");
}
@Override
public void onError(Throwable error) {
System.err.println("\n✗ 错误: " + error.getMessage());
}
});
// 等待完成
Thread.sleep(10000);
}
}
// 2. 自定义Handler
import java.util.concurrent.CompletableFuture;
public class CustomStreamingHandler implements StreamingResponseHandler<String> {
private final StringBuilder fullResponse = new StringBuilder();
private final CompletableFuture<String> future = new CompletableFuture<>();
@Override
public void onNext(String token) {
fullResponse.append(token);
System.out.print(token);
}
@Override
public void onComplete(Response<String> response) {
future.complete(fullResponse.toString());
}
@Override
public void onError(Throwable error) {
future.completeExceptionally(error);
}
public CompletableFuture<String> getFuture() {
return future;
}
}
// 使用
CustomStreamingHandler handler = new CustomStreamingHandler();
model.generate("你好", handler);
String fullResponse = handler.getFuture().get(); // 阻塞等待完成
System.out.println("\n完整响应: " + fullResponse);
// 3. 流式多轮对话
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.message.AiMessage;
public class StreamingConversation {
private final OpenAiStreamingChatModel model;
private final List<ChatMessage> history;
public StreamingConversation() {
this.model = OpenAiStreamingChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
this.history = new ArrayList<>();
}
public void chat(String message) throws Exception {
// 添加用户消息
history.add(new UserMessage(message));
// 流式生成
StringBuilder aiResponse = new StringBuilder();
CountDownLatch latch = new CountDownLatch(1);
model.generate(history, new StreamingResponseHandler<AiMessage>() {
@Override
public void onNext(String token) {
aiResponse.append(token);
System.out.print(token);
}
@Override
public void onComplete(Response<AiMessage> response) {
history.add(response.content());
latch.countDown();
}
@Override
public void onError(Throwable error) {
System.err.println("错误: " + error.getMessage());
latch.countDown();
}
});
latch.await();
System.out.println();
}
}
System.out.println("✓ 流式模型完成");
---
3.2 PromptTemplate
01.模板使用
a.基础模板
a.功能说明
PromptTemplate实现动态提示词生成。支持变量替换和格式化。提高提示词复用性。模板化管理提示词。
b.代码示例
---
// 1. 基础模板
import dev.langchain4j.model.input.Prompt;
import dev.langchain4j.model.input.PromptTemplate;
import java.util.Map;
public class BasicTemplateExample {
public static void main(String[] args) {
// 创建模板
PromptTemplate template = PromptTemplate.from(
"将以下文本翻译为{{language}}:\n\n{{text}}"
);
// 填充变量
Map<String, Object> variables = Map.of(
"language", "英语",
"text", "你好,世界!"
);
Prompt prompt = template.apply(variables);
System.out.println(prompt.text());
// 输出:将以下文本翻译为英语:
// 你好,世界!
// 调用模型
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
String response = model.generate(prompt.text());
System.out.println(response);
}
}
// 2. 多变量模板
public class MultiVariableExample {
public static void main(String[] args) {
PromptTemplate template = PromptTemplate.from(
"""
角色:{{role}}
任务:{{task}}
上下文:{{context}}
要求:{{requirements}}
请完成上述任务。
"""
);
Map<String, Object> variables = Map.of(
"role", "资深Java工程师",
"task", "代码审查",
"context", "Spring Boot微服务项目",
"requirements", "关注性能和安全性"
);
Prompt prompt = template.apply(variables);
System.out.println(prompt.text());
}
}
// 3. 条件模板
public class ConditionalTemplateExample {
public static String createPrompt(String taskType, Map<String, Object> params) {
String templateText = switch (taskType) {
case "translate" -> "将{{text}}翻译为{{language}}";
case "summarize" -> "总结以下内容(不超过{{max_words}}字):\n{{text}}";
case "analyze" -> "分析{{aspect}}:\n{{text}}";
default -> throw new IllegalArgumentException("未知任务类型");
};
PromptTemplate template = PromptTemplate.from(templateText);
return template.apply(params).text();
}
public static void main(String[] args) {
// 翻译任务
String translatePrompt = createPrompt("translate", Map.of(
"text", "Hello",
"language", "中文"
));
System.out.println(translatePrompt);
// 总结任务
String summarizePrompt = createPrompt("summarize", Map.of(
"text", "很长的文章内容...",
"max_words", 100
));
System.out.println(summarizePrompt);
}
}
// 4. 模板继承
public class TemplateInheritance {
// 基础模板
private static final String BASE_TEMPLATE =
"""
系统角色:{{role}}
{{content}}
要求:
{{requirements}}
""";
public static Prompt createPrompt(String role, String content, String requirements) {
PromptTemplate template = PromptTemplate.from(BASE_TEMPLATE);
return template.apply(Map.of(
"role", role,
"content", content,
"requirements", requirements
));
}
public static void main(String[] args) {
Prompt translatorPrompt = createPrompt(
"专业翻译",
"翻译:Hello World",
"准确、流畅"
);
System.out.println(translatorPrompt.text());
}
}
// 5. 从文件加载模板
import java.nio.file.Files;
import java.nio.file.Path;
public class FileTemplateExample {
public static void main(String[] args) throws Exception {
// templates/translate.txt:
// 将以下{{source_lang}}文本翻译为{{target_lang}}:
// {{text}}
String templateText = Files.readString(
Path.of("templates/translate.txt")
);
PromptTemplate template = PromptTemplate.from(templateText);
Prompt prompt = template.apply(Map.of(
"source_lang", "英语",
"target_lang", "中文",
"text", "Hello"
));
System.out.println(prompt.text());
}
}
// 6. 模板验证
public class TemplateValidator {
public static void validateTemplate(PromptTemplate template, Map<String, Object> variables) {
try {
template.apply(variables);
System.out.println("✓ 模板验证通过");
} catch (Exception e) {
System.err.println("✗ 模板验证失败: " + e.getMessage());
}
}
public static void main(String[] args) {
PromptTemplate template = PromptTemplate.from(
"{{name}}说:{{message}}"
);
// 测试完整变量
validateTemplate(template, Map.of(
"name", "张三",
"message", "你好"
));
// 测试缺失变量
validateTemplate(template, Map.of(
"name", "张三"
));
}
}
System.out.println("✓ 基础模板完成");
---
b.高级用法
a.功能说明
支持嵌套模板和列表变量。实现复杂的提示词逻辑。与AI Services集成。高级用法提升灵活性。
b.代码示例
---
// 1. 列表变量
import java.util.List;
public class ListVariableExample {
public static void main(String[] args) {
PromptTemplate template = PromptTemplate.from(
"""
请分析以下问题:
{{#items}}
- {{.}}
{{/items}}
"""
);
Map<String, Object> variables = Map.of(
"items", List.of("性能", "安全性", "可维护性")
);
Prompt prompt = template.apply(variables);
System.out.println(prompt.text());
}
}
// 2. 与AiServices集成
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
interface Translator {
@UserMessage("将{{text}}翻译为{{language}}")
String translate(@V("text") String text, @V("language") String language);
}
public class AiServicesTemplateExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
Translator translator = AiServices.create(Translator.class, model);
String result = translator.translate("你好", "英语");
System.out.println(result);
}
}
// 3. 复杂对象变量
class CodeReviewRequest {
private String code;
private String language;
private List<String> focusAreas;
// Constructor, Getters, Setters
public CodeReviewRequest(String code, String language, List<String> focusAreas) {
this.code = code;
this.language = language;
this.focusAreas = focusAreas;
}
public String getCode() { return code; }
public String getLanguage() { return language; }
public List<String> getFocusAreas() { return focusAreas; }
}
public class ComplexObjectExample {
public static void main(String[] args) {
PromptTemplate template = PromptTemplate.from(
"""
请审查以下{{request.language}}代码:
```
{{request.code}}
```
重点关注:
{{#request.focusAreas}}
- {{.}}
{{/request.focusAreas}}
"""
);
CodeReviewRequest request = new CodeReviewRequest(
"public class Demo { }",
"Java",
List.of("性能", "安全性")
);
Prompt prompt = template.apply(Map.of("request", request));
System.out.println(prompt.text());
}
}
System.out.println("✓ 高级用法完成");
---
3.3 Chain链式调用
01.对话链
a.ConversationalChain
a.功能说明
ConversationalChain管理多轮对话上下文。自动维护对话历史记录。支持记忆窗口配置。实现连续对话能力。
b.代码示例
---
// 1. 基础对话链
import dev.langchain4j.chain.ConversationalChain;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
public class BasicChainExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 创建对话链,保留最近10轮对话
ConversationalChain chain = ConversationalChain.builder()
.chatLanguageModel(model)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.build();
// 第一轮
String r1 = chain.execute("我叫张三");
System.out.println("AI: " + r1);
// 第二轮
String r2 = chain.execute("我喜欢Java编程");
System.out.println("AI: " + r2);
// 第三轮(测试记忆)
String r3 = chain.execute("我叫什么名字?");
System.out.println("AI: " + r3); // 应该回答"张三"
}
}
// 2. 带系统提示的对话链
import dev.langchain4j.data.message.SystemMessage;
public class SystemPromptChainExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
ConversationalChain chain = ConversationalChain.builder()
.chatLanguageModel(model)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.build();
// 设置系统角色
chain.execute(new SystemMessage("你是一个专业的Java导师,用简洁的语言回答问题"));
// 用户对话
String response = chain.execute("什么是泛型?");
System.out.println(response);
}
}
// 3. 自定义记忆窗口
import dev.langchain4j.memory.chat.TokenWindowChatMemory;
import dev.langchain4j.model.Tokenizer;
import dev.langchain4j.model.openai.OpenAiTokenizer;
public class CustomMemoryExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 使用token数量限制记忆(而不是消息数量)
Tokenizer tokenizer = new OpenAiTokenizer("gpt-3.5-turbo");
ConversationalChain chain = ConversationalChain.builder()
.chatLanguageModel(model)
.chatMemory(TokenWindowChatMemory.withMaxTokens(1000, tokenizer))
.build();
String response = chain.execute("你好");
System.out.println(response);
}
}
// 4. 多用户对话链
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class MultiUserChainExample {
private final ChatLanguageModel model;
private final Map<String, ConversationalChain> userChains;
public MultiUserChainExample() {
this.model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
this.userChains = new ConcurrentHashMap<>();
}
public String chat(String userId, String message) {
ConversationalChain chain = userChains.computeIfAbsent(
userId,
id -> ConversationalChain.builder()
.chatLanguageModel(model)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.build()
);
return chain.execute(message);
}
public static void main(String[] args) {
MultiUserChainExample app = new MultiUserChainExample();
// 用户1的对话
System.out.println(app.chat("user1", "我叫张三"));
System.out.println(app.chat("user1", "我叫什么?"));
// 用户2的对话(独立上下文)
System.out.println(app.chat("user2", "我叫李四"));
System.out.println(app.chat("user2", "我叫什么?"));
}
}
// 5. 链式处理
import dev.langchain4j.chain.Chain;
public class ChainProcessingExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
ConversationalChain chain = ConversationalChain.builder()
.chatLanguageModel(model)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.build();
// 链式处理多个问题
List<String> questions = List.of(
"什么是Java?",
"它有什么特点?",
"给个例子"
);
for (String question : questions) {
System.out.println("\n用户: " + question);
String response = chain.execute(question);
System.out.println("AI: " + response);
}
}
}
// 6. 清除记忆
public class MemoryClearExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
MessageWindowChatMemory memory = MessageWindowChatMemory.withMaxMessages(10);
ConversationalChain chain = ConversationalChain.builder()
.chatLanguageModel(model)
.chatMemory(memory)
.build();
chain.execute("我叫张三");
// 清除记忆
memory.clear();
// 不再记得之前的对话
String response = chain.execute("我叫什么名字?");
System.out.println(response); // AI不知道
}
}
System.out.println("✓ ConversationalChain完成");
---
3.4 ChatMemory记忆
01.记忆机制
a.记忆类型
a.功能说明
ChatMemory管理对话历史。支持消息窗口和token窗口两种策略。实现短期和长期记忆。记忆机制是对话连贯性的基础。
b.代码示例
---
// 1. MessageWindowChatMemory
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.message.AiMessage;
public class MessageWindowExample {
public static void main(String[] args) {
// 保留最近5条消息
MessageWindowChatMemory memory = MessageWindowChatMemory.withMaxMessages(5);
// 添加消息
memory.add(new UserMessage("你好"));
memory.add(new AiMessage("你好!有什么可以帮助你的?"));
memory.add(new UserMessage("我叫张三"));
memory.add(new AiMessage("你好,张三!"));
memory.add(new UserMessage("我喜欢编程"));
memory.add(new AiMessage("编程是很有趣的!"));
// 获取所有消息
List<ChatMessage> messages = memory.messages();
System.out.println("消息数量: " + messages.size());
for (ChatMessage message : messages) {
System.out.println(message.text());
}
// 当超过5条时,最早的消息会被移除
memory.add(new UserMessage("我在学Java"));
memory.add(new AiMessage("Java是很好的选择!"));
System.out.println("\n添加新消息后: " + memory.messages().size());
}
}
// 2. TokenWindowChatMemory
import dev.langchain4j.memory.chat.TokenWindowChatMemory;
import dev.langchain4j.model.Tokenizer;
import dev.langchain4j.model.openai.OpenAiTokenizer;
public class TokenWindowExample {
public static void main(String[] args) {
Tokenizer tokenizer = new OpenAiTokenizer("gpt-3.5-turbo");
// 限制最大1000个token
TokenWindowChatMemory memory = TokenWindowChatMemory.withMaxTokens(
1000,
tokenizer
);
memory.add(new UserMessage("你好"));
memory.add(new AiMessage("你好!"));
// 获取当前token数量
List<ChatMessage> messages = memory.messages();
int tokenCount = tokenizer.estimateTokenCountInMessages(messages);
System.out.println("Token数量: " + tokenCount);
}
}
// 3. 自定义记忆存储
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.data.message.ChatMessage;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
public class CustomChatMemory implements ChatMemory {
private final LinkedList<ChatMessage> messages = new LinkedList<>();
private final int maxMessages;
public CustomChatMemory(int maxMessages) {
this.maxMessages = maxMessages;
}
@Override
public void add(ChatMessage message) {
messages.add(message);
// 保持消息数量限制
while (messages.size() > maxMessages) {
messages.removeFirst();
}
System.out.println("添加消息: " + message.text());
}
@Override
public List<ChatMessage> messages() {
return new ArrayList<>(messages);
}
@Override
public void clear() {
messages.clear();
System.out.println("记忆已清除");
}
public static void main(String[] args) {
CustomChatMemory memory = new CustomChatMemory(3);
memory.add(new UserMessage("消息1"));
memory.add(new AiMessage("回复1"));
memory.add(new UserMessage("消息2"));
memory.add(new AiMessage("回复2"));
memory.add(new UserMessage("消息3"));
System.out.println("\n当前消息数: " + memory.messages().size());
}
}
// 4. 持久化记忆
import java.io.*;
import java.util.stream.Collectors;
public class PersistentMemory implements ChatMemory {
private final MessageWindowChatMemory memory;
private final String filePath;
public PersistentMemory(int maxMessages, String filePath) {
this.memory = MessageWindowChatMemory.withMaxMessages(maxMessages);
this.filePath = filePath;
loadFromFile();
}
@Override
public void add(ChatMessage message) {
memory.add(message);
saveToFile();
}
@Override
public List<ChatMessage> messages() {
return memory.messages();
}
@Override
public void clear() {
memory.clear();
saveToFile();
}
private void saveToFile() {
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(filePath)
)) {
oos.writeObject(memory.messages());
} catch (IOException e) {
System.err.println("保存失败: " + e.getMessage());
}
}
@SuppressWarnings("unchecked")
private void loadFromFile() {
File file = new File(filePath);
if (!file.exists()) return;
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(filePath)
)) {
List<ChatMessage> loaded = (List<ChatMessage>) ois.readObject();
loaded.forEach(memory::add);
System.out.println("加载了 " + loaded.size() + " 条消息");
} catch (IOException | ClassNotFoundException e) {
System.err.println("加载失败: " + e.getMessage());
}
}
}
// 5. 数据库记忆
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.beans.factory.annotation.Autowired;
@Entity
class ChatMessageEntity {
@Id
@GeneratedValue
private Long id;
private String sessionId;
private String role; // "user" or "ai"
private String content;
private LocalDateTime timestamp;
// Constructors, Getters, Setters
}
interface ChatMessageRepository extends JpaRepository<ChatMessageEntity, Long> {
List<ChatMessageEntity> findBySessionIdOrderByTimestampAsc(String sessionId);
}
public class DatabaseMemory implements ChatMemory {
@Autowired
private ChatMessageRepository repository;
private final String sessionId;
private final int maxMessages;
public DatabaseMemory(String sessionId, int maxMessages) {
this.sessionId = sessionId;
this.maxMessages = maxMessages;
}
@Override
public void add(ChatMessage message) {
ChatMessageEntity entity = new ChatMessageEntity();
entity.setSessionId(sessionId);
entity.setRole(message instanceof UserMessage ? "user" : "ai");
entity.setContent(message.text());
entity.setTimestamp(LocalDateTime.now());
repository.save(entity);
}
@Override
public List<ChatMessage> messages() {
List<ChatMessageEntity> entities = repository
.findBySessionIdOrderByTimestampAsc(sessionId);
// 只返回最近的maxMessages条
return entities.stream()
.skip(Math.max(0, entities.size() - maxMessages))
.map(entity -> entity.getRole().equals("user")
? new UserMessage(entity.getContent())
: new AiMessage(entity.getContent()))
.collect(Collectors.toList());
}
@Override
public void clear() {
List<ChatMessageEntity> entities = repository
.findBySessionIdOrderByTimestampAsc(sessionId);
repository.deleteAll(entities);
}
}
System.out.println("✓ 记忆类型完成");
---
b.记忆优化
a.功能说明
实现记忆压缩和摘要。优化长对话的token使用。支持重要信息提取。记忆优化提升效率和成本。
b.代码示例
---
// 1. 摘要式记忆
public class SummaryMemory implements ChatMemory {
private final ChatLanguageModel model;
private final List<ChatMessage> recentMessages;
private String summary;
private final int maxRecentMessages;
public SummaryMemory(ChatLanguageModel model, int maxRecentMessages) {
this.model = model;
this.recentMessages = new ArrayList<>();
this.maxRecentMessages = maxRecentMessages;
this.summary = "";
}
@Override
public void add(ChatMessage message) {
recentMessages.add(message);
// 超过限制时,总结并压缩
if (recentMessages.size() > maxRecentMessages) {
compressHistory();
}
}
private void compressHistory() {
// 构建总结提示
StringBuilder historyText = new StringBuilder();
for (ChatMessage msg : recentMessages) {
historyText.append(msg.text()).append("\n");
}
String prompt = String.format(
"之前的对话摘要:%s\n\n" +
"最新对话:\n%s\n\n" +
"请提供一个简洁的摘要,保留关键信息。",
summary,
historyText
);
// 生成摘要
summary = model.generate(prompt);
// 清除旧消息,只保留最近几条
List<ChatMessage> keep = recentMessages.subList(
recentMessages.size() - 3,
recentMessages.size()
);
recentMessages.clear();
recentMessages.addAll(keep);
System.out.println("摘要更新: " + summary);
}
@Override
public List<ChatMessage> messages() {
List<ChatMessage> result = new ArrayList<>();
// 添加摘要(如果有)
if (!summary.isEmpty()) {
result.add(new SystemMessage("对话摘要: " + summary));
}
// 添加最近消息
result.addAll(recentMessages);
return result;
}
@Override
public void clear() {
recentMessages.clear();
summary = "";
}
}
// 2. Redis缓存记忆
import org.springframework.data.redis.core.RedisTemplate;
public class RedisChatMemory implements ChatMemory {
private final RedisTemplate<String, List<ChatMessage>> redisTemplate;
private final String key;
private final int maxMessages;
public RedisChatMemory(
RedisTemplate<String, List<ChatMessage>> redisTemplate,
String sessionId,
int maxMessages
) {
this.redisTemplate = redisTemplate;
this.key = "chat:memory:" + sessionId;
this.maxMessages = maxMessages;
}
@Override
public void add(ChatMessage message) {
List<ChatMessage> messages = redisTemplate.opsForValue().get(key);
if (messages == null) {
messages = new ArrayList<>();
}
messages.add(message);
// 保持数量限制
if (messages.size() > maxMessages) {
messages = messages.subList(
messages.size() - maxMessages,
messages.size()
);
}
// 保存,1小时过期
redisTemplate.opsForValue().set(
key,
messages,
1,
TimeUnit.HOURS
);
}
@Override
public List<ChatMessage> messages() {
List<ChatMessage> messages = redisTemplate.opsForValue().get(key);
return messages != null ? messages : new ArrayList<>();
}
@Override
public void clear() {
redisTemplate.delete(key);
}
}
System.out.println("✓ 记忆优化完成");
---
4 向量存储
4.1 EmbeddingModel
01.嵌入模型
a.OpenAI Embeddings
a.功能说明
使用OpenAI的text-embedding模型生成文本向量。支持单文本和批量嵌入。向量可用于语义搜索和相似度计算。嵌入模型是RAG的核心组件。
b.代码示例
---
// 1. 基础嵌入
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
public class BasicEmbeddingExample {
public static void main(String[] args) {
EmbeddingModel model = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("text-embedding-ada-002")
.build();
// 嵌入单个文本
String text = "LangChain4j是Java的AI框架";
Embedding embedding = model.embed(text).content();
System.out.println("向量维度: " + embedding.dimension()); // 1536
System.out.println("向量数据: " + embedding.vector());
}
}
// 2. 批量嵌入
import dev.langchain4j.model.output.Response;
import java.util.List;
public class BatchEmbeddingExample {
public static void main(String[] args) {
EmbeddingModel model = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 批量嵌入
List<TextSegment> segments = List.of(
TextSegment.from("Java是一门编程语言"),
TextSegment.from("Python也是一门编程语言"),
TextSegment.from("今天天气真好")
);
Response<List<Embedding>> response = model.embedAll(segments);
List<Embedding> embeddings = response.content();
System.out.println("嵌入数量: " + embeddings.size());
for (int i = 0; i < embeddings.size(); i++) {
System.out.println("文本" + i + "向量维度: " +
embeddings.get(i).dimension());
}
}
}
// 3. 相似度计算
import dev.langchain4j.store.embedding.CosineSimilarity;
public class SimilarityExample {
public static void main(String[] args) {
EmbeddingModel model = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 嵌入三个文本
Embedding e1 = model.embed("Java编程").content();
Embedding e2 = model.embed("Java开发").content();
Embedding e3 = model.embed("天气预报").content();
// 计算余弦相似度
double sim12 = CosineSimilarity.between(e1, e2);
double sim13 = CosineSimilarity.between(e1, e3);
System.out.println("Java编程 vs Java开发: " + sim12); // 高相似度
System.out.println("Java编程 vs 天气预报: " + sim13); // 低相似度
}
}
// 4. 文档嵌入
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
public class DocumentEmbeddingExample {
public static void main(String[] args) {
EmbeddingModel model = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 创建文档
Document doc = Document.from(
"LangChain4j是Java生态的AI开发框架。" +
"它支持多种LLM模型和向量数据库。" +
"适合构建企业级AI应用。"
);
// 分割文档
DocumentSplitter splitter = DocumentSplitters.recursive(
100, // chunk大小
10 // overlap
);
List<TextSegment> segments = splitter.split(doc);
// 批量嵌入
List<Embedding> embeddings = model.embedAll(segments).content();
System.out.println("文档被分割为 " + segments.size() + " 个片段");
System.out.println("生成了 " + embeddings.size() + " 个向量");
}
}
// 5. 配置选项
public class ConfiguredEmbeddingExample {
public static void main(String[] args) {
EmbeddingModel model = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("text-embedding-ada-002")
.timeout(Duration.ofSeconds(30))
.maxRetries(3)
.logRequests(true)
.logResponses(true)
.build();
Embedding embedding = model.embed("测试文本").content();
System.out.println("嵌入成功");
}
}
System.out.println("✓ OpenAI Embeddings完成");
---
b.本地嵌入模型
a.功能说明
使用AllMiniLmL6V2等本地模型生成嵌入。无需API调用实现离线运行。适合信创环境和私有部署。本地模型保障数据安全。
b.代码示例
---
// 1. AllMiniLmL6V2模型
/*
Maven依赖:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-all-minilm-l6-v2</artifactId>
<version>${langchain4j.version}</version>
</dependency>
*/
import dev.langchain4j.model.embedding.AllMiniLmL6V2EmbeddingModel;
public class LocalEmbeddingExample {
public static void main(String[] args) {
// 使用本地模型(首次运行会下载模型文件)
EmbeddingModel model = new AllMiniLmL6V2EmbeddingModel();
Embedding embedding = model.embed("你好,世界").content();
System.out.println("向量维度: " + embedding.dimension()); // 384
System.out.println("本地模型嵌入成功");
}
}
// 2. 批量本地嵌入
public class BatchLocalEmbeddingExample {
public static void main(String[] args) {
EmbeddingModel model = new AllMiniLmL6V2EmbeddingModel();
List<TextSegment> segments = List.of(
TextSegment.from("Java编程"),
TextSegment.from("Python开发"),
TextSegment.from("AI应用")
);
List<Embedding> embeddings = model.embedAll(segments).content();
System.out.println("本地批量嵌入完成: " + embeddings.size());
}
}
// 3. 本地与云端对比
public class EmbeddingComparison {
public static void main(String[] args) {
// 本地模型
EmbeddingModel localModel = new AllMiniLmL6V2EmbeddingModel();
// OpenAI模型
EmbeddingModel openaiModel = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
String text = "LangChain4j框架";
// 本地嵌入
long start1 = System.currentTimeMillis();
Embedding local = localModel.embed(text).content();
long time1 = System.currentTimeMillis() - start1;
// 云端嵌入
long start2 = System.currentTimeMillis();
Embedding openai = openaiModel.embed(text).content();
long time2 = System.currentTimeMillis() - start2;
System.out.println("本地模型维度: " + local.dimension() + ", 耗时: " + time1 + "ms");
System.out.println("OpenAI维度: " + openai.dimension() + ", 耗时: " + time2 + "ms");
}
}
// 4. 信创环境集成
public class XinchuangEmbeddingService {
private final EmbeddingModel model;
public XinchuangEmbeddingService() {
// 使用本地模型,无需外网
this.model = new AllMiniLmL6V2EmbeddingModel();
}
public List<Embedding> embedDocuments(List<String> texts) {
List<TextSegment> segments = texts.stream()
.map(TextSegment::from)
.collect(Collectors.toList());
return model.embedAll(segments).content();
}
public static void main(String[] args) {
XinchuangEmbeddingService service = new XinchuangEmbeddingService();
List<String> docs = List.of(
"信创环境文档1",
"信创环境文档2"
);
List<Embedding> embeddings = service.embedDocuments(docs);
System.out.println("信创环境嵌入完成: " + embeddings.size());
}
}
System.out.println("✓ 本地嵌入模型完成");
---
4.2 EmbeddingStore
01.向量存储
a.内存存储
a.功能说明
InMemoryEmbeddingStore提供简单的内存向量存储。适合开发测试和小规模应用。无需外部依赖快速启动。内存存储简单高效。
b.代码示例
---
// 1. 基础内存存储
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.data.embedding.Embedding;
public class InMemoryStoreExample {
public static void main(String[] args) {
// 创建内存存储
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
// 创建嵌入模型
EmbeddingModel model = new AllMiniLmL6V2EmbeddingModel();
// 添加文档
TextSegment segment1 = TextSegment.from("Java编程语言");
Embedding embedding1 = model.embed(segment1).content();
store.add(embedding1, segment1);
TextSegment segment2 = TextSegment.from("Python开发");
Embedding embedding2 = model.embed(segment2).content();
store.add(embedding2, segment2);
System.out.println("已添加2个文档到内存存储");
}
}
// 2. 批量添加
import java.util.List;
public class BatchAddExample {
public static void main(String[] args) {
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
EmbeddingModel model = new AllMiniLmL6V2EmbeddingModel();
// 准备文档
List<TextSegment> segments = List.of(
TextSegment.from("LangChain4j框架"),
TextSegment.from("Spring Boot开发"),
TextSegment.from("微服务架构")
);
// 批量嵌入
List<Embedding> embeddings = model.embedAll(segments).content();
// 批量添加
store.addAll(embeddings, segments);
System.out.println("批量添加完成");
}
}
// 3. 相似度搜索
import dev.langchain4j.store.embedding.EmbeddingMatch;
import dev.langchain4j.store.embedding.EmbeddingSearchRequest;
import dev.langchain4j.store.embedding.EmbeddingSearchResult;
public class SimilaritySearchExample {
public static void main(String[] args) {
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
EmbeddingModel model = new AllMiniLmL6V2EmbeddingModel();
// 添加文档
List<String> documents = List.of(
"Java是一门面向对象的编程语言",
"Python适合数据科学和AI开发",
"Spring Boot简化了Java开发",
"今天天气很好,适合出去玩"
);
for (String doc : documents) {
TextSegment segment = TextSegment.from(doc);
Embedding embedding = model.embed(segment).content();
store.add(embedding, segment);
}
// 搜索
String query = "Java编程";
Embedding queryEmbedding = model.embed(query).content();
EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.maxResults(2)
.minScore(0.7)
.build();
EmbeddingSearchResult<TextSegment> result = store.search(searchRequest);
System.out.println("搜索: " + query);
for (EmbeddingMatch<TextSegment> match : result.matches()) {
System.out.println("相似度: " + match.score() +
", 文档: " + match.embedded().text());
}
}
}
// 4. 元数据过滤
import dev.langchain4j.data.document.Metadata;
public class MetadataFilterExample {
public static void main(String[] args) {
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
EmbeddingModel model = new AllMiniLmL6V2EmbeddingModel();
// 添加带元数据的文档
TextSegment seg1 = TextSegment.from(
"Java基础教程",
Metadata.from("category", "tutorial").put("level", "beginner")
);
store.add(model.embed(seg1).content(), seg1);
TextSegment seg2 = TextSegment.from(
"Java高级特性",
Metadata.from("category", "tutorial").put("level", "advanced")
);
store.add(model.embed(seg2).content(), seg2);
TextSegment seg3 = TextSegment.from(
"Java项目实战",
Metadata.from("category", "project").put("level", "advanced")
);
store.add(model.embed(seg3).content(), seg3);
// 搜索(过滤category=tutorial)
Embedding queryEmbedding = model.embed("Java学习").content();
EmbeddingSearchRequest request = EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.maxResults(10)
.build();
EmbeddingSearchResult<TextSegment> result = store.search(request);
// 手动过滤
result.matches().stream()
.filter(match -> "tutorial".equals(
match.embedded().metadata().getString("category")
))
.forEach(match -> System.out.println(match.embedded().text()));
}
}
// 5. 持久化
import java.io.*;
public class PersistentInMemoryStore {
private final InMemoryEmbeddingStore<TextSegment> store;
private final String filePath;
public PersistentInMemoryStore(String filePath) {
this.filePath = filePath;
this.store = new InMemoryEmbeddingStore<>();
load();
}
public void add(Embedding embedding, TextSegment segment) {
store.add(embedding, segment);
save();
}
public EmbeddingSearchResult<TextSegment> search(EmbeddingSearchRequest request) {
return store.search(request);
}
private void save() {
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(filePath)
)) {
oos.writeObject(store);
} catch (IOException e) {
System.err.println("保存失败: " + e.getMessage());
}
}
@SuppressWarnings("unchecked")
private void load() {
File file = new File(filePath);
if (!file.exists()) return;
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(filePath)
)) {
InMemoryEmbeddingStore<TextSegment> loaded =
(InMemoryEmbeddingStore<TextSegment>) ois.readObject();
// 复制数据到当前store
System.out.println("加载成功");
} catch (IOException | ClassNotFoundException e) {
System.err.println("加载失败: " + e.getMessage());
}
}
}
System.out.println("✓ 内存存储完成");
---
b.外部向量库
a.功能说明
支持Pinecone、Milvus等专业向量数据库。提供高性能和大规模向量检索。适合生产环境。外部向量库提供企业级能力。
b.代码示例
---
// 1. Pinecone集成
/*
Maven依赖:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-pinecone</artifactId>
<version>${langchain4j.version}</version>
</dependency>
*/
import dev.langchain4j.store.embedding.pinecone.PineconeEmbeddingStore;
import io.pinecone.clients.Pinecone;
public class PineconeStoreExample {
public static void main(String[] args) {
// 创建Pinecone客户端
Pinecone pinecone = new Pinecone.Builder(
System.getenv("PINECONE_API_KEY")
).build();
// 创建存储
EmbeddingStore<TextSegment> store = PineconeEmbeddingStore.builder()
.pinecone(pinecone)
.index("my-index")
.namespace("default")
.build();
// 使用与内存存储相同的API
EmbeddingModel model = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
TextSegment segment = TextSegment.from("测试文档");
Embedding embedding = model.embed(segment).content();
store.add(embedding, segment);
System.out.println("已添加到Pinecone");
}
}
// 2. 抽象存储层
public interface DocumentStore {
void addDocument(String text);
List<String> search(String query, int maxResults);
}
public class EmbeddingDocumentStore implements DocumentStore {
private final EmbeddingStore<TextSegment> store;
private final EmbeddingModel model;
public EmbeddingDocumentStore(
EmbeddingStore<TextSegment> store,
EmbeddingModel model
) {
this.store = store;
this.model = model;
}
@Override
public void addDocument(String text) {
TextSegment segment = TextSegment.from(text);
Embedding embedding = model.embed(segment).content();
store.add(embedding, segment);
}
@Override
public List<String> search(String query, int maxResults) {
Embedding queryEmbedding = model.embed(query).content();
EmbeddingSearchRequest request = EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.maxResults(maxResults)
.build();
return store.search(request).matches().stream()
.map(match -> match.embedded().text())
.collect(Collectors.toList());
}
public static void main(String[] args) {
// 可以轻松切换存储实现
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
// 或: PineconeEmbeddingStore.builder()...
EmbeddingModel model = new AllMiniLmL6V2EmbeddingModel();
DocumentStore docStore = new EmbeddingDocumentStore(store, model);
docStore.addDocument("Java编程");
List<String> results = docStore.search("编程语言", 5);
results.forEach(System.out::println);
}
}
System.out.println("✓ 外部向量库完成");
---
4.3 ContentRetriever
01.检索器
a.基础检索
a.功能说明
ContentRetriever实现文档检索逻辑。从向量存储中检索相关文档。支持多种检索策略和过滤条件。检索器是RAG的核心组件。
b.代码示例
---
// 1. EmbeddingStoreContentRetriever
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.rag.query.Query;
import dev.langchain4j.rag.content.Content;
import java.util.List;
public class BasicRetrieverExample {
public static void main(String[] args) {
// 准备存储和模型
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
// 添加文档
List<String> documents = List.of(
"Java是一门面向对象的编程语言",
"Spring Boot是Java的Web框架",
"LangChain4j是AI开发框架"
);
for (String doc : documents) {
TextSegment segment = TextSegment.from(doc);
Embedding embedding = embeddingModel.embed(segment).content();
store.add(embedding, segment);
}
// 创建检索器
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(store)
.embeddingModel(embeddingModel)
.maxResults(2)
.minScore(0.6)
.build();
// 检索
Query query = Query.from("Java开发框架");
List<Content> results = retriever.retrieve(query);
System.out.println("检索到 " + results.size() + " 个结果:");
for (Content content : results) {
System.out.println("- " + content.textSegment().text());
}
}
}
// 2. 带过滤的检索
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.data.document.Metadata;
public class FilteredRetrieverExample {
public static void main(String[] args) {
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
EmbeddingModel model = new AllMiniLmL6V2EmbeddingModel();
// 添加带元数据的文档
addDocument(store, model, "Java基础教程", "tutorial", "beginner");
addDocument(store, model, "Java高级特性", "tutorial", "advanced");
addDocument(store, model, "Spring Boot实战", "project", "advanced");
// 创建检索器
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(store)
.embeddingModel(model)
.maxResults(5)
.build();
// 检索
List<Content> results = retriever.retrieve(Query.from("Java学习"));
// 手动过滤category=tutorial
List<Content> tutorials = results.stream()
.filter(content -> "tutorial".equals(
content.textSegment().metadata().getString("category")
))
.collect(Collectors.toList());
System.out.println("教程文档:");
tutorials.forEach(c -> System.out.println(c.textSegment().text()));
}
private static void addDocument(
EmbeddingStore<TextSegment> store,
EmbeddingModel model,
String text,
String category,
String level
) {
Metadata metadata = Metadata.from("category", category)
.put("level", level);
TextSegment segment = TextSegment.from(text, metadata);
Embedding embedding = model.embed(segment).content();
store.add(embedding, segment);
}
}
// 3. 自定义检索器
public class CustomContentRetriever implements ContentRetriever {
private final EmbeddingStore<TextSegment> store;
private final EmbeddingModel model;
private final int maxResults;
public CustomContentRetriever(
EmbeddingStore<TextSegment> store,
EmbeddingModel model,
int maxResults
) {
this.store = store;
this.model = model;
this.maxResults = maxResults;
}
@Override
public List<Content> retrieve(Query query) {
// 嵌入查询
Embedding queryEmbedding = model.embed(query.text()).content();
// 检索
EmbeddingSearchRequest request = EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.maxResults(maxResults)
.minScore(0.5)
.build();
EmbeddingSearchResult<TextSegment> searchResult = store.search(request);
// 转换为Content
return searchResult.matches().stream()
.map(match -> Content.from(match.embedded()))
.collect(Collectors.toList());
}
public static void main(String[] args) {
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
EmbeddingModel model = new AllMiniLmL6V2EmbeddingModel();
ContentRetriever retriever = new CustomContentRetriever(store, model, 3);
List<Content> results = retriever.retrieve(Query.from("测试"));
System.out.println("自定义检索完成");
}
}
// 4. 重排序检索
public class ReRankingRetriever implements ContentRetriever {
private final ContentRetriever baseRetriever;
private final ChatLanguageModel reRankModel;
public ReRankingRetriever(
ContentRetriever baseRetriever,
ChatLanguageModel reRankModel
) {
this.baseRetriever = baseRetriever;
this.reRankModel = reRankModel;
}
@Override
public List<Content> retrieve(Query query) {
// 初步检索
List<Content> candidates = baseRetriever.retrieve(query);
if (candidates.isEmpty()) {
return candidates;
}
// 使用LLM重排序
String prompt = String.format(
"查询: %s\n\n" +
"以下文档按相关性排序(最相关的在前):\n%s\n\n" +
"返回文档编号,用逗号分隔(如:2,0,1)",
query.text(),
formatCandidates(candidates)
);
String response = reRankModel.generate(prompt);
// 解析排序结果
List<Integer> order = parseOrder(response);
// 重新排序
return order.stream()
.filter(i -> i < candidates.size())
.map(candidates::get)
.collect(Collectors.toList());
}
private String formatCandidates(List<Content> candidates) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < candidates.size(); i++) {
sb.append(i).append(". ")
.append(candidates.get(i).textSegment().text())
.append("\n");
}
return sb.toString();
}
private List<Integer> parseOrder(String response) {
try {
return Arrays.stream(response.trim().split(","))
.map(String::trim)
.map(Integer::parseInt)
.collect(Collectors.toList());
} catch (Exception e) {
return List.of();
}
}
}
// 5. 混合检索
public class HybridRetriever implements ContentRetriever {
private final ContentRetriever semanticRetriever;
private final KeywordSearchRetriever keywordRetriever;
public HybridRetriever(
ContentRetriever semanticRetriever,
KeywordSearchRetriever keywordRetriever
) {
this.semanticRetriever = semanticRetriever;
this.keywordRetriever = keywordRetriever;
}
@Override
public List<Content> retrieve(Query query) {
// 语义检索
List<Content> semanticResults = semanticRetriever.retrieve(query);
// 关键词检索
List<Content> keywordResults = keywordRetriever.search(query.text());
// 合并去重
Set<String> seen = new HashSet<>();
List<Content> combined = new ArrayList<>();
for (Content content : semanticResults) {
String text = content.textSegment().text();
if (seen.add(text)) {
combined.add(content);
}
}
for (Content content : keywordResults) {
String text = content.textSegment().text();
if (seen.add(text)) {
combined.add(content);
}
}
return combined;
}
}
// 模拟关键词检索器
class KeywordSearchRetriever {
public List<Content> search(String query) {
// 简单的关键词匹配
return List.of();
}
}
System.out.println("✓ 基础检索完成");
---
5 AI Services
5.1 声明式接口
01.AiServices
a.基础用法
a.功能说明
AiServices提供声明式AI服务接口。通过注解定义提示词模板。自动处理模型调用和响应解析。声明式接口简化开发。
b.代码示例
---
// 1. 基础接口
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.UserMessage;
interface Assistant {
@UserMessage("你好,我的名字是{{name}}")
String greet(String name);
}
public class BasicAiServiceExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
Assistant assistant = AiServices.create(Assistant.class, model);
String response = assistant.greet("张三");
System.out.println(response);
}
}
// 2. 系统消息
import dev.langchain4j.service.SystemMessage;
interface Translator {
@SystemMessage("你是一个专业翻译")
@UserMessage("将{{text}}翻译为{{language}}")
String translate(String text, String language);
}
public class SystemMessageExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
Translator translator = AiServices.create(Translator.class, model);
String result = translator.translate("你好", "英语");
System.out.println(result); // "Hello"
}
}
// 3. 结构化输出
class Person {
private String name;
private int age;
private String occupation;
// Constructors, Getters, Setters
public Person() {}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getOccupation() { return occupation; }
public void setOccupation(String occupation) { this.occupation = occupation; }
}
interface PersonExtractor {
@UserMessage("从以下文本提取人物信息:{{text}}")
Person extract(String text);
}
public class StructuredOutputExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
PersonExtractor extractor = AiServices.create(PersonExtractor.class, model);
Person person = extractor.extract("张三,25岁,软件工程师");
System.out.println("姓名: " + person.getName());
System.out.println("年龄: " + person.getAge());
System.out.println("职业: " + person.getOccupation());
}
}
// 4. 枚举返回值
enum Sentiment {
POSITIVE, NEGATIVE, NEUTRAL
}
interface SentimentAnalyzer {
@UserMessage("分析情感:{{text}}")
Sentiment analyze(String text);
}
public class EnumReturnExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
SentimentAnalyzer analyzer = AiServices.create(SentimentAnalyzer.class, model);
Sentiment sentiment1 = analyzer.analyze("今天天气真好!");
System.out.println(sentiment1); // POSITIVE
Sentiment sentiment2 = analyzer.analyze("糟糕的一天");
System.out.println(sentiment2); // NEGATIVE
}
}
// 5. 列表返回值
interface KeywordExtractor {
@UserMessage("从以下文本提取关键词:{{text}}")
List<String> extractKeywords(String text);
}
public class ListReturnExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
KeywordExtractor extractor = AiServices.create(KeywordExtractor.class, model);
List<String> keywords = extractor.extractKeywords(
"LangChain4j是Java的AI开发框架,支持多种LLM模型"
);
System.out.println("关键词: " + keywords);
}
}
// 6. @V注解(变量注入)
import dev.langchain4j.service.V;
interface TemplateService {
@UserMessage("角色:{{role}},任务:{{task}}")
String execute(@V("role") String role, @V("task") String task);
}
public class VariableAnnotationExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
TemplateService service = AiServices.create(TemplateService.class, model);
String response = service.execute("Java导师", "解释泛型");
System.out.println(response);
}
}
// 7. 多方法接口
interface MultiMethodAssistant {
@UserMessage("将{{text}}翻译为英语")
String translateToEnglish(String text);
@UserMessage("将{{text}}翻译为中文")
String translateToChinese(String text);
@UserMessage("总结:{{text}}")
String summarize(String text);
}
public class MultiMethodExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
MultiMethodAssistant assistant = AiServices.create(
MultiMethodAssistant.class,
model
);
String en = assistant.translateToEnglish("你好");
System.out.println("英语: " + en);
String zh = assistant.translateToChinese("Hello");
System.out.println("中文: " + zh);
String summary = assistant.summarize("很长的文章内容...");
System.out.println("摘要: " + summary);
}
}
// 8. 带记忆的接口
interface ChatAssistant {
String chat(String message);
}
public class MemoryServiceExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
ChatMemory memory = MessageWindowChatMemory.withMaxMessages(10);
ChatAssistant assistant = AiServices.builder(ChatAssistant.class)
.chatLanguageModel(model)
.chatMemory(memory)
.build();
System.out.println(assistant.chat("我叫张三"));
System.out.println(assistant.chat("我叫什么名字?"));
}
}
System.out.println("✓ 基础用法完成");
---
5.2 工具调用
01.函数调用
a.@Tool注解
a.功能说明
@Tool注解定义AI可调用的工具函数。AI自动判断何时调用工具。支持参数传递和返回值。工具调用扩展AI能力。
b.代码示例
---
// 1. 基础工具
import dev.langchain4j.agent.tool.Tool;
class Calculator {
@Tool("计算两个数的和")
public int add(int a, int b) {
System.out.println("调用工具: add(" + a + ", " + b + ")");
return a + b;
}
@Tool("计算两个数的乘积")
public int multiply(int a, int b) {
System.out.println("调用工具: multiply(" + a + ", " + b + ")");
return a * b;
}
}
interface MathAssistant {
String chat(String message);
}
public class BasicToolExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
Calculator calculator = new Calculator();
MathAssistant assistant = AiServices.builder(MathAssistant.class)
.chatLanguageModel(model)
.tools(calculator)
.build();
String response1 = assistant.chat("15加27等于多少?");
System.out.println(response1);
String response2 = assistant.chat("6乘以8是多少?");
System.out.println(response2);
}
}
// 2. 复杂工具
class WeatherService {
@Tool("获取指定城市的天气信息")
public String getWeather(String city) {
System.out.println("查询天气: " + city);
// 模拟API调用
return switch (city) {
case "北京" -> "晴天,20度";
case "上海" -> "多云,18度";
default -> "未知城市";
};
}
@Tool("获取未来几天的天气预报")
public String getForecast(String city, int days) {
System.out.println("查询预报: " + city + ", " + days + "天");
return city + "未来" + days + "天:晴转多云";
}
}
interface WeatherAssistant {
String chat(String message);
}
public class ComplexToolExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
WeatherService weather = new WeatherService();
WeatherAssistant assistant = AiServices.builder(WeatherAssistant.class)
.chatLanguageModel(model)
.tools(weather)
.build();
String response = assistant.chat("北京今天天气怎么样?");
System.out.println(response);
}
}
// 3. 多个工具
class DatabaseTools {
@Tool("查询用户信息")
public String getUserInfo(String userId) {
return "用户" + userId + ": 张三, 25岁";
}
@Tool("查询订单信息")
public String getOrderInfo(String orderId) {
return "订单" + orderId + ": 已发货";
}
}
class CalculationTools {
@Tool("计算折扣价格")
public double calculateDiscount(double price, double discount) {
return price * (1 - discount);
}
}
interface BusinessAssistant {
String chat(String message);
}
public class MultipleToolsExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
DatabaseTools dbTools = new DatabaseTools();
CalculationTools calcTools = new CalculationTools();
BusinessAssistant assistant = AiServices.builder(BusinessAssistant.class)
.chatLanguageModel(model)
.tools(dbTools, calcTools)
.build();
String response1 = assistant.chat("查询用户user123的信息");
System.out.println(response1);
String response2 = assistant.chat("100元打8折是多少?");
System.out.println(response2);
}
}
// 4. 工具执行日志
import dev.langchain4j.agent.tool.ToolExecutionRequest;
import dev.langchain4j.agent.tool.ToolExecutor;
class LoggingTools {
@Tool("发送邮件")
public String sendEmail(String to, String subject) {
String log = String.format(
"发送邮件 - 收件人: %s, 主题: %s",
to, subject
);
System.out.println(log);
return "邮件已发送";
}
}
// 5. 异步工具
import java.util.concurrent.CompletableFuture;
class AsyncTools {
@Tool("异步查询数据")
public CompletableFuture<String> queryData(String query) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000); // 模拟耗时操作
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "查询结果: " + query;
});
}
}
System.out.println("✓ @Tool注解完成");
---
b.工具集成
a.功能说明
集成外部服务和API作为工具。实现数据库查询、文件操作等功能。工具使AI能够执行实际操作。工具集成实现端到端自动化。
b.代码示例
---
// 1. 数据库工具
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.beans.factory.annotation.Autowired;
class DatabaseQueryTools {
@Autowired
private JdbcTemplate jdbcTemplate;
@Tool("查询用户数量")
public int countUsers() {
return jdbcTemplate.queryForObject(
"SELECT COUNT(*) FROM users",
Integer.class
);
}
@Tool("根据ID查询用户")
public String findUserById(Long userId) {
return jdbcTemplate.queryForObject(
"SELECT username FROM users WHERE id = ?",
String.class,
userId
);
}
}
// 2. HTTP API工具
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
class ApiTools {
private final HttpClient client = HttpClient.newHttpClient();
@Tool("调用REST API获取数据")
public String callApi(String endpoint) {
try {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/" + endpoint))
.GET()
.build();
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
return response.body();
} catch (Exception e) {
return "API调用失败: " + e.getMessage();
}
}
}
// 3. 文件操作工具
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
class FileTools {
@Tool("读取文件内容")
public String readFile(String filePath) {
try {
Path path = Paths.get(filePath);
return Files.readString(path);
} catch (Exception e) {
return "文件读取失败: " + e.getMessage();
}
}
@Tool("写入文件")
public String writeFile(String filePath, String content) {
try {
Path path = Paths.get(filePath);
Files.writeString(path, content);
return "文件写入成功";
} catch (Exception e) {
return "文件写入失败: " + e.getMessage();
}
}
}
// 4. 信创环境工具
import dmPython.DmConnection;
import dmPython.DmStatement;
class XinchuangTools {
private final DmConnection dmConnection;
public XinchuangTools(String connectionString) {
this.dmConnection = dmPython.connect(connectionString);
}
@Tool("查询达梦数据库")
public String queryDameng(String sql) {
try {
DmStatement stmt = dmConnection.createStatement();
// 执行查询
return "查询结果";
} catch (Exception e) {
return "查询失败: " + e.getMessage();
}
}
@Tool("调用本地Ollama模型")
public String callOllama(String prompt) {
ChatLanguageModel ollama = OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen:7b")
.build();
return ollama.generate(prompt);
}
}
System.out.println("✓ 工具集成完成");
---
5.3 RAG集成
01.检索增强
a.基础RAG
a.功能说明
将ContentRetriever集成到AiServices实现RAG。自动检索相关文档补充上下文。提升AI回答的准确性和相关性。RAG是知识库问答的核心技术。
b.代码示例
---
// 1. 基础RAG集成
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
interface KnowledgeBaseAssistant {
String answer(String question);
}
public class BasicRAGExample {
public static void main(String[] args) {
// 准备向量存储
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
// 添加知识库文档
addKnowledge(store, embeddingModel,
"LangChain4j是Java生态的AI开发框架");
addKnowledge(store, embeddingModel,
"LangChain4j支持OpenAI、Ollama等多种LLM");
addKnowledge(store, embeddingModel,
"LangChain4j提供向量存储和RAG能力");
// 创建检索器
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(store)
.embeddingModel(embeddingModel)
.maxResults(2)
.build();
// 创建ChatModel
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 创建RAG服务
KnowledgeBaseAssistant assistant = AiServices.builder(KnowledgeBaseAssistant.class)
.chatLanguageModel(model)
.contentRetriever(retriever)
.build();
// 提问
String answer = assistant.answer("LangChain4j支持哪些LLM?");
System.out.println(answer);
}
private static void addKnowledge(
EmbeddingStore<TextSegment> store,
EmbeddingModel model,
String text
) {
TextSegment segment = TextSegment.from(text);
Embedding embedding = model.embed(segment).content();
store.add(embedding, segment);
}
}
// 2. 文档加载RAG
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.document.parser.TextDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
public class DocumentRAGExample {
public static void main(String[] args) {
// 加载文档
Document doc = FileSystemDocumentLoader.loadDocument(
"knowledge.txt",
new TextDocumentParser()
);
// 分割文档
List<TextSegment> segments = DocumentSplitters.recursive(300, 50)
.split(doc);
System.out.println("文档分割为 " + segments.size() + " 个片段");
// 嵌入并存储
EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
store.addAll(embeddings, segments);
// 创建RAG服务
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(store)
.embeddingModel(embeddingModel)
.maxResults(3)
.build();
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
KnowledgeBaseAssistant assistant = AiServices.builder(KnowledgeBaseAssistant.class)
.chatLanguageModel(model)
.contentRetriever(retriever)
.build();
String answer = assistant.answer("文档的主要内容是什么?");
System.out.println(answer);
}
}
// 3. 多轮对话RAG
interface ConversationalRAGAssistant {
String chat(String message);
}
public class ConversationalRAGExample {
public static void main(String[] args) {
// 准备知识库
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
// 添加知识
String[] knowledge = {
"Java 17是LTS版本,发布于2021年",
"Java 21是最新的LTS版本",
"Spring Boot 3需要Java 17+",
"LangChain4j推荐使用Java 17或更高版本"
};
for (String k : knowledge) {
TextSegment seg = TextSegment.from(k);
store.add(embeddingModel.embed(seg).content(), seg);
}
// 创建检索器
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(store)
.embeddingModel(embeddingModel)
.maxResults(2)
.build();
// 创建服务(带记忆)
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
ChatMemory memory = MessageWindowChatMemory.withMaxMessages(10);
ConversationalRAGAssistant assistant = AiServices.builder(ConversationalRAGAssistant.class)
.chatLanguageModel(model)
.chatMemory(memory)
.contentRetriever(retriever)
.build();
// 多轮对话
System.out.println(assistant.chat("Java 17是什么时候发布的?"));
System.out.println(assistant.chat("那最新的LTS版本呢?"));
System.out.println(assistant.chat("Spring Boot 3需要什么版本?"));
}
}
// 4. 自定义RAG策略
import dev.langchain4j.rag.DefaultRetrievalAugmentor;
import dev.langchain4j.rag.RetrievalAugmentor;
import dev.langchain4j.rag.query.Query;
import dev.langchain4j.rag.content.Content;
public class CustomRAGStrategy {
public static void main(String[] args) {
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(store)
.embeddingModel(embeddingModel)
.maxResults(5)
.build();
// 自定义增强器
RetrievalAugmentor augmentor = DefaultRetrievalAugmentor.builder()
.contentRetriever(retriever)
.build();
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
KnowledgeBaseAssistant assistant = AiServices.builder(KnowledgeBaseAssistant.class)
.chatLanguageModel(model)
.retrievalAugmentor(augmentor)
.build();
String answer = assistant.answer("测试问题");
System.out.println(answer);
}
}
// 5. 信创环境RAG
public class XinchuangRAGExample {
public static void main(String[] args) {
// 使用本地模型和向量存储
EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
// 添加信创相关知识
String[] xinchuangKnowledge = {
"信创环境使用Ollama部署本地大模型",
"达梦数据库是国产关系型数据库",
"国密算法包括SM2、SM3、SM4"
};
for (String k : xinchuangKnowledge) {
TextSegment seg = TextSegment.from(k);
store.add(embeddingModel.embed(seg).content(), seg);
}
// 使用本地LLM
ChatLanguageModel model = OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen:7b")
.build();
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(store)
.embeddingModel(embeddingModel)
.maxResults(2)
.build();
KnowledgeBaseAssistant assistant = AiServices.builder(KnowledgeBaseAssistant.class)
.chatLanguageModel(model)
.contentRetriever(retriever)
.build();
String answer = assistant.answer("信创环境如何部署大模型?");
System.out.println(answer);
}
}
System.out.println("✓ 基础RAG完成");
---
6 模型集成
6.1 OpenAI集成
01.OpenAI模型
a.Chat模型配置
a.功能说明
OpenAiChatModel支持GPT-3.5和GPT-4系列模型。配置temperature、max_tokens等参数。支持流式输出和函数调用。OpenAI是最成熟的LLM服务。
b.代码示例
---
// 1. 基础配置
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiChatModelName;
public class OpenAIConfigExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(OpenAiChatModelName.GPT_3_5_TURBO)
.temperature(0.7)
.maxTokens(1000)
.topP(1.0)
.frequencyPenalty(0.0)
.presencePenalty(0.0)
.timeout(Duration.ofSeconds(30))
.maxRetries(3)
.logRequests(true)
.logResponses(true)
.build();
String response = model.generate("介绍Java");
System.out.println(response);
}
}
// 2. GPT-4配置
public class GPT4Example {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(OpenAiChatModelName.GPT_4)
.temperature(0.3) // 更低的temperature获得更确定的输出
.maxTokens(2000)
.build();
String response = model.generate("详细解释Java泛型的工作原理");
System.out.println(response);
}
}
// 3. 自定义端点
public class CustomEndpointExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.baseUrl("https://api.openai.com/v1") // 自定义端点
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-3.5-turbo")
.build();
String response = model.generate("测试");
System.out.println(response);
}
}
// 4. 代理配置
import java.net.InetSocketAddress;
import java.net.Proxy;
public class ProxyExample {
public static void main(String[] args) {
Proxy proxy = new Proxy(
Proxy.Type.HTTP,
new InetSocketAddress("proxy.example.com", 8080)
);
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.proxy(proxy)
.build();
String response = model.generate("测试");
System.out.println(response);
}
}
// 5. Token使用统计
import dev.langchain4j.model.output.Response;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.message.AiMessage;
public class TokenUsageExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
List<ChatMessage> messages = List.of(
new UserMessage("介绍一下Java")
);
Response<AiMessage> response = model.generate(messages);
System.out.println("内容: " + response.content().text());
System.out.println("输入tokens: " + response.tokenUsage().inputTokenCount());
System.out.println("输出tokens: " + response.tokenUsage().outputTokenCount());
System.out.println("总tokens: " + response.tokenUsage().totalTokenCount());
}
}
// 6. 模型切换
public class ModelSwitcher {
private final ChatLanguageModel gpt35;
private final ChatLanguageModel gpt4;
public ModelSwitcher() {
String apiKey = System.getenv("OPENAI_API_KEY");
this.gpt35 = OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName(OpenAiChatModelName.GPT_3_5_TURBO)
.build();
this.gpt4 = OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName(OpenAiChatModelName.GPT_4)
.build();
}
public String chat(String message, boolean useGPT4) {
ChatLanguageModel model = useGPT4 ? gpt4 : gpt35;
return model.generate(message);
}
public static void main(String[] args) {
ModelSwitcher switcher = new ModelSwitcher();
// 简单问题使用GPT-3.5
String simple = switcher.chat("什么是Java?", false);
System.out.println("GPT-3.5: " + simple);
// 复杂问题使用GPT-4
String complex = switcher.chat("设计一个分布式系统架构", true);
System.out.println("GPT-4: " + complex);
}
}
System.out.println("✓ Chat模型配置完成");
---
b.Embedding模型
a.功能说明
OpenAiEmbeddingModel提供文本向量化能力。使用text-embedding-ada-002模型。生成1536维的向量表示。适合语义搜索和相似度计算。
b.代码示例
---
// 1. 基础嵌入
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
public class OpenAIEmbeddingExample {
public static void main(String[] args) {
EmbeddingModel model = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("text-embedding-ada-002")
.build();
String text = "LangChain4j是Java的AI框架";
Embedding embedding = model.embed(text).content();
System.out.println("维度: " + embedding.dimension());
System.out.println("前5个值: " +
embedding.vector().subList(0, 5));
}
}
// 2. 批量嵌入优化
public class BatchEmbeddingOptimized {
public static void main(String[] args) {
EmbeddingModel model = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 批量嵌入比单个嵌入更高效
List<String> texts = List.of(
"文本1",
"文本2",
"文本3",
"文本4",
"文本5"
);
long start = System.currentTimeMillis();
List<TextSegment> segments = texts.stream()
.map(TextSegment::from)
.collect(Collectors.toList());
List<Embedding> embeddings = model.embedAll(segments).content();
long duration = System.currentTimeMillis() - start;
System.out.println("批量嵌入5个文本耗时: " + duration + "ms");
System.out.println("生成向量数: " + embeddings.size());
}
}
// 3. 嵌入缓存
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class CachedEmbeddingModel implements EmbeddingModel {
private final EmbeddingModel delegate;
private final Map<String, Embedding> cache;
public CachedEmbeddingModel(EmbeddingModel delegate) {
this.delegate = delegate;
this.cache = new ConcurrentHashMap<>();
}
@Override
public Response<Embedding> embed(String text) {
Embedding cached = cache.get(text);
if (cached != null) {
System.out.println("缓存命中: " + text);
return Response.from(cached);
}
Response<Embedding> response = delegate.embed(text);
cache.put(text, response.content());
return response;
}
@Override
public Response<Embedding> embed(TextSegment textSegment) {
return embed(textSegment.text());
}
@Override
public Response<List<Embedding>> embedAll(List<TextSegment> segments) {
return delegate.embedAll(segments);
}
public static void main(String[] args) {
EmbeddingModel openai = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
EmbeddingModel cached = new CachedEmbeddingModel(openai);
// 第一次调用(无缓存)
cached.embed("测试文本");
// 第二次调用(命中缓存)
cached.embed("测试文本");
}
}
System.out.println("✓ Embedding模型完成");
---
6.2 本地模型
01.Ollama集成
a.基础配置
a.功能说明
Ollama支持本地部署LLM模型。无需API Key实现离线运行。支持Qwen、Llama等开源模型。适合信创和私有部署环境。
b.代码示例
---
// 1. Ollama基础配置
import dev.langchain4j.model.ollama.OllamaChatModel;
public class OllamaBasicExample {
public static void main(String[] args) {
ChatLanguageModel model = OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen:7b")
.temperature(0.7)
.build();
String response = model.generate("你好,介绍一下Java");
System.out.println(response);
}
}
// 2. 配置参数
public class OllamaConfiguredExample {
public static void main(String[] args) {
ChatLanguageModel model = OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen:7b")
.temperature(0.7)
.topK(40)
.topP(0.9)
.repeatPenalty(1.1)
.seed(42)
.numPredict(1000)
.timeout(Duration.ofMinutes(2))
.build();
String response = model.generate("详细介绍Spring Boot");
System.out.println(response);
}
}
// 3. 流式输出
import dev.langchain4j.model.ollama.OllamaStreamingChatModel;
import dev.langchain4j.model.StreamingResponseHandler;
public class OllamaStreamingExample {
public static void main(String[] args) throws InterruptedException {
var model = OllamaStreamingChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen:7b")
.build();
System.out.print("AI: ");
model.generate("讲一个故事", new StreamingResponseHandler<String>() {
@Override
public void onNext(String token) {
System.out.print(token);
}
@Override
public void onComplete(Response<String> response) {
System.out.println("\n\n✓ 完成");
}
@Override
public void onError(Throwable error) {
System.err.println("\n✗ 错误: " + error.getMessage());
}
});
Thread.sleep(30000); // 等待完成
}
}
// 4. 多模型管理
public class OllamaModelManager {
private final String baseUrl;
private final Map<String, ChatLanguageModel> models;
public OllamaModelManager(String baseUrl) {
this.baseUrl = baseUrl;
this.models = new ConcurrentHashMap<>();
}
public ChatLanguageModel getModel(String modelName) {
return models.computeIfAbsent(modelName, name ->
OllamaChatModel.builder()
.baseUrl(baseUrl)
.modelName(name)
.build()
);
}
public String chat(String modelName, String message) {
ChatLanguageModel model = getModel(modelName);
return model.generate(message);
}
public static void main(String[] args) {
OllamaModelManager manager = new OllamaModelManager(
"http://localhost:11434"
);
// 使用不同模型
String qwen = manager.chat("qwen:7b", "你好");
System.out.println("Qwen: " + qwen);
String llama = manager.chat("llama2", "Hello");
System.out.println("Llama: " + llama);
}
}
// 5. Ollama嵌入模型
import dev.langchain4j.model.ollama.OllamaEmbeddingModel;
public class OllamaEmbeddingExample {
public static void main(String[] args) {
EmbeddingModel model = OllamaEmbeddingModel.builder()
.baseUrl("http://localhost:11434")
.modelName("nomic-embed-text")
.build();
String text = "LangChain4j框架";
Embedding embedding = model.embed(text).content();
System.out.println("向量维度: " + embedding.dimension());
}
}
// 6. 健康检查
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class OllamaHealthCheck {
public static boolean isOllamaReady(String baseUrl) {
try {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/api/tags"))
.GET()
.build();
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
return response.statusCode() == 200;
} catch (Exception e) {
return false;
}
}
public static void main(String[] args) {
String baseUrl = "http://localhost:11434";
if (isOllamaReady(baseUrl)) {
System.out.println("Ollama服务正常");
ChatLanguageModel model = OllamaChatModel.builder()
.baseUrl(baseUrl)
.modelName("qwen:7b")
.build();
String response = model.generate("测试");
System.out.println(response);
} else {
System.err.println("Ollama服务不可用");
}
}
}
System.out.println("✓ Ollama基础配置完成");
---
b.信创环境部署
a.功能说明
在信创环境中部署Ollama服务。使用国产化硬件和操作系统。部署Qwen等国产大模型。实现完全离线的AI能力。
b.代码示例
---
// 1. 信创环境配置
public class XinchuangOllamaExample {
public static void main(String[] args) {
// 信创环境Ollama配置
ChatLanguageModel model = OllamaChatModel.builder()
.baseUrl("http://xinchuang-server:11434") // 信创服务器
.modelName("qwen:7b") // 通义千问
.temperature(0.7)
.timeout(Duration.ofMinutes(5))
.build();
String response = model.generate("介绍信创技术");
System.out.println(response);
}
}
// 2. 国密通信
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.net.ssl.SSLContext;
import java.security.Security;
public class SM2OllamaClient {
static {
Security.addProvider(new BouncyCastleProvider());
}
public static ChatLanguageModel createSecureModel() {
// 配置SM2/SM3/SM4国密算法
// 实际实现需要根据具体需求配置SSL
return OllamaChatModel.builder()
.baseUrl("https://xinchuang-server:11434")
.modelName("qwen:7b")
.build();
}
public static void main(String[] args) {
ChatLanguageModel model = createSecureModel();
String response = model.generate("测试国密通信");
System.out.println(response);
}
}
// 3. 达梦数据库集成
import dmPython.DmConnection;
import dmPython.DmStatement;
public class DamengOllamaService {
private final ChatLanguageModel model;
private final DmConnection dmConnection;
public DamengOllamaService(String dbUrl, String ollamaUrl) {
this.dmConnection = dmPython.connect(dbUrl);
this.model = OllamaChatModel.builder()
.baseUrl(ollamaUrl)
.modelName("qwen:7b")
.build();
}
public void saveConversation(String userId, String question, String answer) {
try {
DmStatement stmt = dmConnection.createStatement();
String sql = String.format(
"INSERT INTO conversations (user_id, question, answer, created_at) " +
"VALUES ('%s', '%s', '%s', CURRENT_TIMESTAMP)",
userId, question, answer
);
stmt.execute(sql);
System.out.println("对话已保存到达梦数据库");
} catch (Exception e) {
System.err.println("保存失败: " + e.getMessage());
}
}
public String chat(String userId, String question) {
String answer = model.generate(question);
saveConversation(userId, question, answer);
return answer;
}
public static void main(String[] args) {
DamengOllamaService service = new DamengOllamaService(
"jdbc:dm://localhost:5236/SYSDBA",
"http://localhost:11434"
);
String response = service.chat("user123", "什么是信创?");
System.out.println(response);
}
}
// 4. 麒麟系统适配
public class KylinOllamaService {
public static void main(String[] args) {
// 检测操作系统
String os = System.getProperty("os.name");
System.out.println("操作系统: " + os);
// Ollama在麒麟系统上运行
ChatLanguageModel model = OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen:7b")
.build();
String response = model.generate("介绍麒麟操作系统");
System.out.println(response);
}
}
// 5. 昇腾NPU加速
public class AscendOllamaExample {
public static void main(String[] args) {
// Ollama配置使用昇腾NPU
// 需要在Ollama服务端配置NPU支持
ChatLanguageModel model = OllamaChatModel.builder()
.baseUrl("http://ascend-server:11434")
.modelName("qwen:7b") // 在NPU上加速推理
.build();
long start = System.currentTimeMillis();
String response = model.generate("测试NPU加速效果");
long duration = System.currentTimeMillis() - start;
System.out.println("响应: " + response);
System.out.println("耗时: " + duration + "ms");
}
}
System.out.println("✓ 信创环境部署完成");
---
6.3 自定义模型
01.自定义实现
a.实现ChatLanguageModel接口
a.功能说明
实现ChatLanguageModel接口适配自定义LLM服务。统一接口便于模型切换和管理。支持企业内部模型和第三方服务。自定义模型扩展框架能力。
b.代码示例
---
// 1. 自定义ChatLanguageModel
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.AiMessage;
public class CustomChatModel implements ChatLanguageModel {
private final String apiEndpoint;
private final String apiKey;
public CustomChatModel(String apiEndpoint, String apiKey) {
this.apiEndpoint = apiEndpoint;
this.apiKey = apiKey;
}
@Override
public String generate(String userMessage) {
// 实现API调用逻辑
try {
return callApi(userMessage);
} catch (Exception e) {
return "调用失败: " + e.getMessage();
}
}
@Override
public Response<AiMessage> generate(List<ChatMessage> messages) {
// 构建请求
String prompt = buildPrompt(messages);
// 调用API
String responseText = callApi(prompt);
// 构建响应
AiMessage aiMessage = new AiMessage(responseText);
return Response.from(aiMessage);
}
@Override
public Response<AiMessage> generate(
List<ChatMessage> messages,
List<ToolSpecification> toolSpecifications
) {
// 带工具调用的实现
return generate(messages);
}
private String buildPrompt(List<ChatMessage> messages) {
StringBuilder sb = new StringBuilder();
for (ChatMessage message : messages) {
sb.append(message.text()).append("\n");
}
return sb.toString();
}
private String callApi(String prompt) {
// 模拟API调用
System.out.println("调用自定义API: " + apiEndpoint);
return "这是自定义模型的响应";
}
public static void main(String[] args) {
ChatLanguageModel model = new CustomChatModel(
"https://custom-llm.example.com/api",
"custom-api-key"
);
String response = model.generate("你好");
System.out.println(response);
}
}
// 2. HTTP客户端实现
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
public class HttpBasedChatModel implements ChatLanguageModel {
private final HttpClient client;
private final String endpoint;
private final String apiKey;
private final Gson gson;
public HttpBasedChatModel(String endpoint, String apiKey) {
this.client = HttpClient.newHttpClient();
this.endpoint = endpoint;
this.apiKey = apiKey;
this.gson = new Gson();
}
@Override
public String generate(String userMessage) {
try {
// 构建请求体
JsonObject requestBody = new JsonObject();
requestBody.addProperty("prompt", userMessage);
requestBody.addProperty("max_tokens", 1000);
// 创建请求
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + apiKey)
.POST(HttpRequest.BodyPublishers.ofString(
gson.toJson(requestBody)
))
.build();
// 发送请求
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
// 解析响应
JsonObject responseJson = gson.fromJson(
response.body(),
JsonObject.class
);
return responseJson.get("text").getAsString();
} catch (Exception e) {
throw new RuntimeException("API调用失败", e);
}
}
@Override
public Response<AiMessage> generate(List<ChatMessage> messages) {
String prompt = messages.stream()
.map(ChatMessage::text)
.collect(Collectors.joining("\n"));
String response = generate(prompt);
return Response.from(new AiMessage(response));
}
public static void main(String[] args) {
ChatLanguageModel model = new HttpBasedChatModel(
"https://api.example.com/chat",
"your-api-key"
);
String response = model.generate("介绍Java");
System.out.println(response);
}
}
// 3. 模型包装器
public class LoggingChatModelWrapper implements ChatLanguageModel {
private final ChatLanguageModel delegate;
public LoggingChatModelWrapper(ChatLanguageModel delegate) {
this.delegate = delegate;
}
@Override
public String generate(String userMessage) {
System.out.println("[LOG] 输入: " + userMessage);
long start = System.currentTimeMillis();
String response = delegate.generate(userMessage);
long duration = System.currentTimeMillis() - start;
System.out.println("[LOG] 输出: " + response);
System.out.println("[LOG] 耗时: " + duration + "ms");
return response;
}
@Override
public Response<AiMessage> generate(List<ChatMessage> messages) {
System.out.println("[LOG] 多轮对话,消息数: " + messages.size());
return delegate.generate(messages);
}
public static void main(String[] args) {
ChatLanguageModel base = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
ChatLanguageModel logged = new LoggingChatModelWrapper(base);
String response = logged.generate("你好");
System.out.println(response);
}
}
// 4. 缓存模型
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class CachedChatModel implements ChatLanguageModel {
private final ChatLanguageModel delegate;
private final Map<String, String> cache;
public CachedChatModel(ChatLanguageModel delegate) {
this.delegate = delegate;
this.cache = new ConcurrentHashMap<>();
}
@Override
public String generate(String userMessage) {
return cache.computeIfAbsent(userMessage, key -> {
System.out.println("缓存未命中,调用模型");
return delegate.generate(key);
});
}
@Override
public Response<AiMessage> generate(List<ChatMessage> messages) {
// 简化:只缓存单消息
if (messages.size() == 1) {
String text = messages.get(0).text();
String response = generate(text);
return Response.from(new AiMessage(response));
}
return delegate.generate(messages);
}
public void clearCache() {
cache.clear();
}
}
// 5. 重试模型
public class RetryableChatModel implements ChatLanguageModel {
private final ChatLanguageModel delegate;
private final int maxRetries;
public RetryableChatModel(ChatLanguageModel delegate, int maxRetries) {
this.delegate = delegate;
this.maxRetries = maxRetries;
}
@Override
public String generate(String userMessage) {
int attempt = 0;
Exception lastException = null;
while (attempt < maxRetries) {
try {
return delegate.generate(userMessage);
} catch (Exception e) {
lastException = e;
attempt++;
System.err.println("重试 " + attempt + "/" + maxRetries);
try {
Thread.sleep(1000 * attempt); // 指数退避
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
throw new RuntimeException("重试失败", lastException);
}
@Override
public Response<AiMessage> generate(List<ChatMessage> messages) {
String prompt = messages.stream()
.map(ChatMessage::text)
.collect(Collectors.joining("\n"));
String response = generate(prompt);
return Response.from(new AiMessage(response));
}
}
// 6. 组合使用
public class ComposedModelExample {
public static void main(String[] args) {
// 基础模型
ChatLanguageModel base = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 添加重试
ChatLanguageModel withRetry = new RetryableChatModel(base, 3);
// 添加缓存
ChatLanguageModel withCache = new CachedChatModel(withRetry);
// 添加日志
ChatLanguageModel final model = new LoggingChatModelWrapper(withCache);
// 使用
String response = finalModel.generate("你好");
System.out.println(response);
// 第二次调用(命中缓存)
String response2 = finalModel.generate("你好");
System.out.println(response2);
}
}
System.out.println("✓ 自定义实现完成");
---
7 Spring Boot集成
7.1 Starter配置
01.自动配置
a.添加Starter依赖
a.功能说明
LangChain4j提供Spring Boot Starter实现自动配置。通过application.yml配置模型参数。支持多种模型的自动装配。Starter简化Spring集成。
b.代码示例
---
// 1. Maven依赖
/*
<dependencies>
<!-- LangChain4j Spring Boot Starter -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>0.27.1</version>
</dependency>
<!-- OpenAI Spring Boot Starter -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
<version>0.27.1</version>
</dependency>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
*/
// 2. application.yml配置
/*
langchain4j:
open-ai:
chat-model:
api-key: ${OPENAI_API_KEY}
model-name: gpt-3.5-turbo
temperature: 0.7
max-tokens: 1000
timeout: 30s
max-retries: 3
log-requests: true
log-responses: true
embedding-model:
api-key: ${OPENAI_API_KEY}
model-name: text-embedding-ada-002
*/
// 3. 启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LangChain4jApplication {
public static void main(String[] args) {
SpringApplication.run(LangChain4jApplication.class, args);
}
}
// 4. 自动注入使用
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import dev.langchain4j.model.chat.ChatLanguageModel;
@RestController
@RequestMapping("/api")
public class ChatController {
private final ChatLanguageModel chatModel;
@Autowired
public ChatController(ChatLanguageModel chatModel) {
this.chatModel = chatModel;
}
@PostMapping("/chat")
public ChatResponse chat(@RequestBody ChatRequest request) {
String response = chatModel.generate(request.getMessage());
return new ChatResponse(response);
}
}
// 请求/响应类
record ChatRequest(String message) {}
record ChatResponse(String response) {}
// 5. 多环境配置
/*
# application-dev.yml
langchain4j:
open-ai:
chat-model:
api-key: ${OPENAI_API_KEY}
model-name: gpt-3.5-turbo
log-requests: true
# application-prod.yml
langchain4j:
open-ai:
chat-model:
api-key: ${OPENAI_API_KEY}
model-name: gpt-4
log-requests: false
*/
// 6. 自定义Bean
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.AllMiniLmL6V2EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
@Configuration
public class LangChain4jConfig {
@Bean
public EmbeddingModel embeddingModel() {
return new AllMiniLmL6V2EmbeddingModel();
}
@Bean
public EmbeddingStore<TextSegment> embeddingStore() {
return new InMemoryEmbeddingStore<>();
}
@Bean
public ChatMemory chatMemory() {
return MessageWindowChatMemory.withMaxMessages(10);
}
}
System.out.println("✓ Starter依赖完成");
---
b.配置属性
a.功能说明
通过ConfigurationProperties管理配置。支持IDE配置提示和验证。实现类型安全的配置管理。配置属性提升开发体验。
b.代码示例
---
// 1. 配置属性类
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import jakarta.validation.constraints.*;
@Component
@ConfigurationProperties(prefix = "app.langchain4j")
public class LangChain4jProperties {
@NotBlank
private String apiKey;
private String modelName = "gpt-3.5-turbo";
@DecimalMin("0.0")
@DecimalMax("2.0")
private Double temperature = 0.7;
@Min(1)
@Max(4000)
private Integer maxTokens = 1000;
@Min(1)
@Max(10)
private Integer maxRetries = 3;
private Integer timeoutSeconds = 30;
// Getters and Setters
public String getApiKey() { return apiKey; }
public void setApiKey(String apiKey) { this.apiKey = apiKey; }
public String getModelName() { return modelName; }
public void setModelName(String modelName) { this.modelName = modelName; }
public Double getTemperature() { return temperature; }
public void setTemperature(Double temperature) { this.temperature = temperature; }
public Integer getMaxTokens() { return maxTokens; }
public void setMaxTokens(Integer maxTokens) { this.maxTokens = maxTokens; }
public Integer getMaxRetries() { return maxRetries; }
public void setMaxRetries(Integer maxRetries) { this.maxRetries = maxRetries; }
public Integer getTimeoutSeconds() { return timeoutSeconds; }
public void setTimeoutSeconds(Integer timeoutSeconds) {
this.timeoutSeconds = timeoutSeconds;
}
}
// 2. 使用配置属性
import org.springframework.beans.factory.annotation.Autowired;
@Configuration
public class ModelConfiguration {
@Autowired
private LangChain4jProperties properties;
@Bean
public ChatLanguageModel chatLanguageModel() {
return OpenAiChatModel.builder()
.apiKey(properties.getApiKey())
.modelName(properties.getModelName())
.temperature(properties.getTemperature())
.maxTokens(properties.getMaxTokens())
.maxRetries(properties.getMaxRetries())
.timeout(Duration.ofSeconds(properties.getTimeoutSeconds()))
.build();
}
}
// 3. YAML配置
/*
app:
langchain4j:
api-key: ${OPENAI_API_KEY}
model-name: gpt-3.5-turbo
temperature: 0.7
max-tokens: 1000
max-retries: 3
timeout-seconds: 30
*/
// 4. 配置校验
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.validation.annotation.Validated;
@Configuration
@EnableConfigurationProperties(LangChain4jProperties.class)
@Validated
public class ValidationConfig {
// 启用配置验证
}
System.out.println("✓ 配置属性完成");
---
7.2 依赖注入
01.服务层注入
a.Service层使用
a.功能说明
在Service层注入ChatLanguageModel和相关组件。实现业务逻辑与AI能力的结合。支持事务管理和AOP。依赖注入实现松耦合架构。
b.代码示例
---
// 1. 基础Service
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import dev.langchain4j.model.chat.ChatLanguageModel;
@Service
public class ChatService {
private final ChatLanguageModel model;
@Autowired
public ChatService(ChatLanguageModel model) {
this.model = model;
}
public String chat(String message) {
return model.generate(message);
}
public String chatWithContext(String userId, String message) {
// 添加用户上下文
String prompt = String.format(
"用户ID: %s\n问题: %s",
userId, message
);
return model.generate(prompt);
}
}
// 2. RAG Service
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.service.AiServices;
interface KnowledgeBaseAssistant {
String answer(String question);
}
@Service
public class KnowledgeBaseService {
private final KnowledgeBaseAssistant assistant;
@Autowired
public KnowledgeBaseService(
ChatLanguageModel model,
ContentRetriever retriever
) {
this.assistant = AiServices.builder(KnowledgeBaseAssistant.class)
.chatLanguageModel(model)
.contentRetriever(retriever)
.build();
}
public String queryKnowledgeBase(String question) {
return assistant.answer(question);
}
}
// 3. 多模型Service
@Service
public class MultiModelService {
private final ChatLanguageModel primaryModel;
private final ChatLanguageModel fallbackModel;
@Autowired
public MultiModelService(
@Qualifier("openAiModel") ChatLanguageModel primaryModel,
@Qualifier("ollamaModel") ChatLanguageModel fallbackModel
) {
this.primaryModel = primaryModel;
this.fallbackModel = fallbackModel;
}
public String chatWithFallback(String message) {
try {
return primaryModel.generate(message);
} catch (Exception e) {
System.err.println("主模型失败,使用备用模型");
return fallbackModel.generate(message);
}
}
}
// 4. 事务管理
import org.springframework.transaction.annotation.Transactional;
import org.springframework.jdbc.core.JdbcTemplate;
@Service
public class TransactionalChatService {
private final ChatLanguageModel model;
private final JdbcTemplate jdbcTemplate;
@Autowired
public TransactionalChatService(
ChatLanguageModel model,
JdbcTemplate jdbcTemplate
) {
this.model = model;
this.jdbcTemplate = jdbcTemplate;
}
@Transactional
public String chatAndSave(String userId, String message) {
// 调用AI模型
String response = model.generate(message);
// 保存到数据库
String sql = "INSERT INTO chat_history (user_id, message, response) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, userId, message, response);
return response;
}
}
// 5. 缓存Service
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheEvict;
@Service
public class CachedChatService {
private final ChatLanguageModel model;
@Autowired
public CachedChatService(ChatLanguageModel model) {
this.model = model;
}
@Cacheable(value = "chatResponses", key = "#message")
public String chat(String message) {
System.out.println("调用模型(未缓存)");
return model.generate(message);
}
@CacheEvict(value = "chatResponses", allEntries = true)
public void clearCache() {
System.out.println("清除缓存");
}
}
// 6. 异步Service
import org.springframework.scheduling.annotation.Async;
import java.util.concurrent.CompletableFuture;
@Service
public class AsyncChatService {
private final ChatLanguageModel model;
@Autowired
public AsyncChatService(ChatLanguageModel model) {
this.model = model;
}
@Async
public CompletableFuture<String> chatAsync(String message) {
String response = model.generate(message);
return CompletableFuture.completedFuture(response);
}
}
System.out.println("✓ Service层使用完成");
---
7.3 自动配置
01.自动装配
a.Conditional注解
a.功能说明
使用@Conditional注解实现按条件自动配置。根据环境和依赖动态加载Bean。支持多环境和多模型配置。自动装配简化配置管理。
b.代码示例
---
// 1. 条件配置
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConditionalModelConfig {
@Bean
@ConditionalOnProperty(name = "langchain4j.provider", havingValue = "openai")
public ChatLanguageModel openAiModel() {
return OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
}
@Bean
@ConditionalOnProperty(name = "langchain4j.provider", havingValue = "ollama")
public ChatLanguageModel ollamaModel() {
return OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen:7b")
.build();
}
}
// application.yml: langchain4j.provider=openai
// 2. 自定义AutoConfiguration
@Configuration
@ConditionalOnClass(ChatLanguageModel.class)
public class LangChain4jAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public ChatLanguageModel defaultChatModel() {
return OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen:7b")
.build();
}
@Bean
@ConditionalOnMissingBean
public EmbeddingModel defaultEmbeddingModel() {
return new AllMiniLmL6V2EmbeddingModel();
}
}
System.out.println("✓ 自动装配完成");
---
8 实战案例
8.1 企业知识库
01.知识库实现
a.文档管理
a.功能说明
实现企业文档的加载、分割和向量化。支持PDF、Word等多种格式。实现文档的增删改查。知识库是RAG应用的基础。
b.代码示例
---
// 1. 文档加载Service
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.document.parser.*;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
import org.springframework.stereotype.Service;
@Service
public class DocumentService {
private final EmbeddingModel embeddingModel;
private final EmbeddingStore<TextSegment> store;
@Autowired
public DocumentService(
EmbeddingModel embeddingModel,
EmbeddingStore<TextSegment> store
) {
this.embeddingModel = embeddingModel;
this.store = store;
}
public void loadDocument(String filePath) {
// 加载文档
DocumentParser parser = getParser(filePath);
Document doc = FileSystemDocumentLoader.loadDocument(filePath, parser);
// 分割文档
List<TextSegment> segments = DocumentSplitters
.recursive(300, 50)
.split(doc);
// 向量化并存储
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
store.addAll(embeddings, segments);
System.out.println("文档加载完成: " + segments.size() + " 个片段");
}
private DocumentParser getParser(String filePath) {
if (filePath.endsWith(".pdf")) {
return new ApachePdfBoxDocumentParser();
} else if (filePath.endsWith(".txt")) {
return new TextDocumentParser();
}
throw new IllegalArgumentException("不支持的文件类型");
}
}
// 2. 知识库查询
interface KnowledgeBaseAssistant {
String answer(String question);
}
@Service
public class KnowledgeBaseService {
private final KnowledgeBaseAssistant assistant;
@Autowired
public KnowledgeBaseService(
ChatLanguageModel model,
EmbeddingModel embeddingModel,
EmbeddingStore<TextSegment> store
) {
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(store)
.embeddingModel(embeddingModel)
.maxResults(3)
.build();
this.assistant = AiServices.builder(KnowledgeBaseAssistant.class)
.chatLanguageModel(model)
.contentRetriever(retriever)
.build();
}
public String query(String question) {
return assistant.answer(question);
}
}
// 3. REST API
@RestController
@RequestMapping("/api/knowledge")
public class KnowledgeBaseController {
@Autowired
private KnowledgeBaseService service;
@Autowired
private DocumentService documentService;
@PostMapping("/upload")
public ResponseEntity<String> uploadDocument(@RequestParam("file") MultipartFile file) throws Exception {
// 保存文件
String filePath = "/tmp/" + file.getOriginalFilename();
file.transferTo(new File(filePath));
// 加载到知识库
documentService.loadDocument(filePath);
return ResponseEntity.ok("文档上传成功");
}
@PostMapping("/query")
public QueryResponse query(@RequestBody QueryRequest request) {
String answer = service.query(request.question());
return new QueryResponse(answer);
}
}
record QueryRequest(String question) {}
record QueryResponse(String answer) {}
System.out.println("✓ 企业知识库完成");
---
8.2 智能客服
01.客服系统
a.多轮对话
a.功能说明
实现智能客服的多轮对话能力。维护用户对话历史和上下文。支持意图识别和问题分类。智能客服提升服务效率。
b.代码示例
---
// 1. 客服Service
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
interface CustomerServiceAgent {
@SystemMessage("你是一个专业的客服助手,礼貌且高效地回答用户问题")
String chat(String message);
}
@Service
public class CustomerServiceImpl {
private final ChatLanguageModel model;
private final Map<String, CustomerServiceAgent> userAgents;
@Autowired
public CustomerServiceImpl(ChatLanguageModel model) {
this.model = model;
this.userAgents = new ConcurrentHashMap<>();
}
public String chat(String userId, String message) {
CustomerServiceAgent agent = userAgents.computeIfAbsent(
userId,
id -> createAgent()
);
return agent.chat(message);
}
private CustomerServiceAgent createAgent() {
ChatMemory memory = MessageWindowChatMemory.withMaxMessages(10);
return AiServices.builder(CustomerServiceAgent.class)
.chatLanguageModel(model)
.chatMemory(memory)
.build();
}
}
// 2. REST API
@RestController
@RequestMapping("/api/customer-service")
public class CustomerServiceController {
@Autowired
private CustomerServiceImpl service;
@PostMapping("/chat")
public ChatResponse chat(@RequestBody ChatRequest request) {
String response = service.chat(request.userId(), request.message());
return new ChatResponse(response);
}
}
record ChatRequest(String userId, String message) {}
record ChatResponse(String response) {}
System.out.println("✓ 智能客服完成");
---
8.3 API网关
01.API设计
a.RESTful接口
a.功能说明
设计统一的RESTful API接口。支持流式和非流式两种模式。实现请求限流和认证。API网关是对外服务的入口。
b.代码示例
---
// 1. 统一API
import org.springframework.web.bind.annotation.*;
import org.springframework.http.MediaType;
import reactor.core.publisher.Flux;
@RestController
@RequestMapping("/api/v1/chat")
public class ChatAPIController {
@Autowired
private ChatLanguageModel model;
@PostMapping("/completions")
public CompletionResponse completions(@RequestBody CompletionRequest request) {
String response = model.generate(request.prompt());
return new CompletionResponse(response);
}
@PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> stream(@RequestBody CompletionRequest request) {
// 流式响应实现
return Flux.create(sink -> {
// 实现流式输出
sink.next("响应片段");
sink.complete();
});
}
}
record CompletionRequest(String prompt, Double temperature) {}
record CompletionResponse(String text) {}
System.out.println("✓ API网关完成");
---
9 最佳实践
9.1 性能调优
01.优化策略
a.连接池优化
a.功能说明
使用连接池管理HTTP连接。复用连接减少开销。配置合理的超时和重试。连接池优化提升性能。
b.代码示例
---
// 1. HTTP客户端配置
import java.net.http.HttpClient;
import java.time.Duration;
@Configuration
public class HttpClientConfig {
@Bean
public HttpClient httpClient() {
return HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
}
}
// 2. 批量处理
@Service
public class BatchProcessingService {
@Autowired
private ChatLanguageModel model;
public List<String> processBatch(List<String> messages) {
return messages.parallelStream()
.map(model::generate)
.collect(Collectors.toList());
}
}
System.out.println("✓ 性能调优完成");
---
9.2 异常处理
01.错误管理
a.全局异常处理
a.功能说明
使用@ControllerAdvice统一处理异常。区分业务异常和系统异常。返回友好的错误信息。异常处理提升系统健壮性。
b.代码示例
---
// 1. 全局异常处理器
import org.springframework.web.bind.annotation.*;
import org.springframework.http.*;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception e) {
ErrorResponse error = new ErrorResponse(
"INTERNAL_ERROR",
e.getMessage()
);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<ErrorResponse> handleIllegalArgument(IllegalArgumentException e) {
ErrorResponse error = new ErrorResponse(
"INVALID_REQUEST",
e.getMessage()
);
return ResponseEntity.badRequest().body(error);
}
}
record ErrorResponse(String code, String message) {}
// 2. 重试机制
@Service
public class ResilientChatService {
@Autowired
private ChatLanguageModel model;
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000))
public String chatWithRetry(String message) {
return model.generate(message);
}
}
System.out.println("✓ 异常处理完成");
---
9.3 生产部署
01.部署策略
a.Docker容器化
a.功能说明
使用Docker容器化部署应用。配置环境变量和资源限制。实现快速部署和扩缩容。容器化是现代部署的标准。
b.代码示例
---
// 1. Dockerfile
/*
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENV OPENAI_API_KEY=""
ENV OLLAMA_BASE_URL="http://ollama:11434"
ENTRYPOINT ["java", "-jar", "app.jar"]
*/
// 2. docker-compose.yml
/*
version: '3.8'
services:
langchain4j-app:
build: .
ports:
- "8080:8080"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- SPRING_PROFILES_ACTIVE=prod
depends_on:
- ollama
ollama:
image: ollama/ollama:latest
ports:
- "11434:11434"
volumes:
- ollama-data:/root/.ollama
volumes:
ollama-data:
*/
// 3. Kubernetes部署
/*
apiVersion: apps/v1
kind: Deployment
metadata:
name: langchain4j-app
spec:
replicas: 3
selector:
matchLabels:
app: langchain4j
template:
metadata:
labels:
app: langchain4j
spec:
containers:
- name: langchain4j
image: langchain4j-app:latest
ports:
- containerPort: 8080
env:
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: langchain4j-secrets
key: openai-api-key
*/
// 4. 健康检查
import org.springframework.boot.actuate.health.*;
import org.springframework.stereotype.Component;
@Component
public class LangChain4jHealthIndicator implements HealthIndicator {
@Autowired
private ChatLanguageModel model;
@Override
public Health health() {
try {
model.generate("health check");
return Health.up().withDetail("model", "available").build();
} catch (Exception e) {
return Health.down().withDetail("error", e.getMessage()).build();
}
}
}
System.out.println("✓ 生产部署完成");
---