聊聊langchain4j的ChatMemory

本文主要研究一下langchain4j的ChatMemory

ChatMemory

langchain4j-core/src/main/java/dev/langchain4j/memory/ChatMemory.java

public interface ChatMemory {

    /**
     * The ID of the {@link ChatMemory}.
     * @return The ID of the {@link ChatMemory}.
     */
    Object id();

    /**
     * Adds a message to the chat memory.
     *
     * @param message The {@link ChatMessage} to add.
     */
    void add(ChatMessage message);

    /**
     * Retrieves messages from the chat memory.
     * Depending on the implementation, it may not return all previously added messages,
     * but rather a subset, a summary, or a combination thereof.
     *
     * @return A list of {@link ChatMessage} objects that represent the current state of the chat memory.
     */
    List<ChatMessage> messages();

    /**
     * Clears the chat memory.
     */
    void clear();
}

ChatMemory定义了id、add、messages、clear方法,它有MessageWindowChatMemory、TokenWindowChatMemory两个实现

public class MessageWindowChatMemory implements ChatMemory {

    private static final Logger log = LoggerFactory.getLogger(MessageWindowChatMemory.class);

    private final Object id;
    private final Integer maxMessages;
    private final ChatMemoryStore store;

    private MessageWindowChatMemory(Builder builder) {
        this.id = ensureNotNull(builder.id, "id");
        this.maxMessages = ensureGreaterThanZero(builder.maxMessages, "maxMessages");
        this.store = ensureNotNull(builder.store, "store");
    }

    @Override
    public Object id() {
        return id;
    }

    @Override
    public void add(ChatMessage message) {
        List<ChatMessage> messages = messages();
        if (message instanceof SystemMessage) {
            Optional<SystemMessage> systemMessage = findSystemMessage(messages);
            if (systemMessage.isPresent()) {
                if (systemMessage.get().equals(message)) {
                    return; // do not add the same system message
                } else {
                    messages.remove(systemMessage.get()); // need to replace existing system message
                }
            }
        }
        messages.add(message);
        ensureCapacity(messages, maxMessages);
        store.updateMessages(id, messages);
    }

    private static Optional<SystemMessage> findSystemMessage(List<ChatMessage> messages) {
        return messages.stream()
                .filter(message -> message instanceof SystemMessage)
                .map(message -> (SystemMessage) message)
                .findAny();
    }

    @Override
    public List<ChatMessage> messages() {
        List<ChatMessage> messages = new LinkedList<>(store.getMessages(id));
        ensureCapacity(messages, maxMessages);
        return messages;
    }

    private static void ensureCapacity(List<ChatMessage> messages, int maxMessages) {
        while (messages.size() > maxMessages) {

            int messageToEvictIndex = 0;
            if (messages.get(0) instanceof SystemMessage) {
                messageToEvictIndex = 1;
            }

            ChatMessage evictedMessage = messages.remove(messageToEvictIndex);
            log.trace("Evicting the following message to comply with the capacity requirement: {}", evictedMessage);

            if (evictedMessage instanceof AiMessage && ((AiMessage) evictedMessage).hasToolExecutionRequests()) {
                while (messages.size() > messageToEvictIndex
                        && messages.get(messageToEvictIndex) instanceof ToolExecutionResultMessage) {
                    // Some LLMs (e.g. OpenAI) prohibit ToolExecutionResultMessage(s) without corresponding AiMessage,
                    // so we have to automatically evict orphan ToolExecutionResultMessage(s) if AiMessage was evicted
                    ChatMessage orphanToolExecutionResultMessage = messages.remove(messageToEvictIndex);
                    log.trace("Evicting orphan {}", orphanToolExecutionResultMessage);
                }
            }
        }
    }

    @Override
    public void clear() {
        store.deleteMessages(id);
    }

    //......
}    

MessageWindowChatMemory默认使用的是InMemoryChatMemoryStore;ensureCapacity方法用来确保message不超过maxMessages,超过则从list的头部开始移除;SystemMessage一旦添加了就会一直保留,每次只能保留一个SystemMessage,添加相同的SystemMessage会被忽略,不同的SystemMessage会保留最新的

### 使用 LangChain4j 实现豆包大模型功能集成的示例代码 LangChain4j 是一个用于简化与大语言模型(LLM)交互的框架,支持多种 LLM 集成,包括豆包大模型。以下是实现豆包大模型功能集成的具体步骤和示例代码。 #### 1. 添加 Maven 依赖 在项目中引入 LangChain4j 的核心库,确保可以使用其提供的功能[^3]。 ```xml <dependency> <groupId>com.langchain4j</groupId> <artifactId>langchain4j-core</artifactId> <version>最新版本号</version> </dependency> ``` #### 2. 初始化豆包大模型客户端 通过 LangChain4j 提供的 API,初始化豆包大模型客户端,并配置相关参数[^1]。 ```java import com.langchain4j.llm.doubean.DouBeanLLM; import com.langchain4j.chain.ConversationChain; public class DouBeanExample { public static void main(String[] args) { // 初始化豆包大模型客户端 DouBeanLLM douBeanLLM = DouBeanLLM.builder() .apiKey("你的豆包API密钥") .model("doubean-model-1") // 指定使用的模型 .temperature(0.7) // 设置生成温度 .maxTokens(256) // 设置最大生成令牌数 .build(); } } ``` #### 3. 创建会话链(ConversationChain) 利用 `ConversationChain` 构建对话链,以便在多次交互中保持上下文信息[^1]。 ```java // 创建 ConversationChain ConversationChain conversationChain = ConversationChain.builder() .llm(douBeanLLM) .build(); // 发起第一次对话 String response1 = conversationChain.call("你好,豆包!"); System.out.println("第一次响应: " + response1); // 继续对话,保持上下文 String response2 = conversationChain.call("我们来聊聊人工智能吧!"); System.out.println("第二次响应: " + response2); ``` #### 4. 直接调用大模型完成任务 如果不需要复杂的上下文管理,可以直接调用大模型完成特定任务[^1]。 ```java // 直接调用豆包大模型生成文本 String result = douBeanLLM.generate("请为我生成一首关于秋天的诗。"); System.out.println("生成的诗歌: " + result); ``` #### 5. 配置项目入口 类似于 LangChain4j 示例项目的结构,在主类中实现上述逻辑[^2]。 ```java public class App { public static void main(String[] args) { // 初始化豆包大模型客户端 DouBeanLLM douBeanLLM = DouBeanLLM.builder() .apiKey("你的豆包API密钥") .model("doubean-model-1") .temperature(0.7) .maxTokens(256) .build(); // 创建 ConversationChain ConversationChain conversationChain = ConversationChain.builder() .llm(douBeanLLM) .build(); // 测试对话 String response1 = conversationChain.call("你好,豆包!"); System.out.println("第一次响应: " + response1); String response2 = conversationChain.call("我们来聊聊人工智能吧!"); System.out.println("第二次响应: " + response2); } } ``` ### 注意事项 - 确保正确配置 API 密钥和模型名称[^1]。 - 如果需要流式输出功能,可以参考 LangChain4j 和 Spring WebFlux 的结合案例[^5]。 - 在生产环境中,建议对 SSE 连接超时、中文乱码等问题进行排查并优化[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值