langchain4j [特性] 保持系统消息在聊天内存中的第一个位置

ih99xse1  于 2个月前  发布在  其他
关注(0)|答案(4)|浏览(39)

您的功能请求是否与问题相关?请描述。

ChatMemory 实现在处理 SystemMessage 的位置时表现得有些奇怪。

  • SystemMessage 首先被添加时,它会被保留为第一个项目
  • 当一个 SystemMessage 消息被添加,无论是在 UserMessage 之后还是在第一个 SystemMessage 之后,它都会被放在最后一个位置
  • 在驱逐过程中,SystemMessage 的位置会在内存中向上移动,直到达到第一个位置并保持在那里。
    描述您希望的解决方案

我希望标准化和简化 SystemMessage 的位置处理,使其始终保持在列表中的第一条消息。

描述您考虑过的替代方案

我可以重新实现(添加自己的实现)或者代理现有的实现:MessageWindowChatMemoryTokenWindowChatMemory

附加上下文

基于当前 langchain4j:0.30.0 的状态
我可以提出一些建议来解决这个问题吗?

yquaqz18

yquaqz181#

你好,当前行为背后有一些逻辑(稍后我可以解释一下)。但是你看到问题了吗?你看到LLM的行为不符合你的期望吗?谢谢。

woobm2wo

woobm2wo2#

使用以下示例,我使用了简单的ChatMemory实现,让我能够真正控制消息的顺序(以展示现有实现可能发生的情况)

public class ChatMemoryExamples {
    public static class SimpleChatMemory implements ChatMemory {
        private List<ChatMessage> messages = new ArrayList<>();

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

        @Override
        public void add(ChatMessage message) {
            messages.add(message);
        }

        @Override
        public List<ChatMessage> messages() {
            return new ArrayList<>(messages);
        }

        @Override
        public void clear() {
            messages.clear();
        }
    }

    public static class BadPositionningSystemMessage_Example {
        public static void main(String[] args) throws IOException {
            ChatLanguageModel model = OpenAiChatModel.withApiKey(ApiKeys.OPENAI_API_KEY);
            SystemMessage systemMessage = new SystemMessage("provide answer to user questions even if it is not real time data. format the result of user question using asciidoc format");
            UserMessage userFormatMessage = new UserMessage("format the result of the following questions using xml format");
            UserMessage userQuestion = new UserMessage("provide me the list of the 10 biggest cities in term on inhabitants in the USA");
            AiMessage response;

            ChatMemory memory = new SimpleChatMemory();
            memory.add(systemMessage);
            memory.add(userFormatMessage);
            memory.add(userQuestion);

            response = model.generate(memory.messages()).content();
            System.out.println("With ordered messages:");
            System.out.println(memory.messages());

            System.out.println("Answer:");
            System.out.println(response.text());

            memory.clear();
            memory.add(userFormatMessage);
            memory.add(systemMessage);
            memory.add(userQuestion);

            response = model.generate(memory.messages()).content();
            System.out.println("With ordered messages:");
            System.out.println(memory.messages());

            System.out.println("Answer:");
            System.out.println(response.text());
        }
    }
}

答案如下

With ordered messages:
    [SystemMessage { text = "provide answer to user questions even if it is not real time data. format the result of user question using asciidoc format" }, UserMessage { name = null contents = [TextContent { text = "format the result of the following questions using xml format" }] }, UserMessage { name = null contents = [TextContent { text = "provide me the list of the 10 biggest cities in term on inhabitants in the USA" }] }]
    Answer:
    Below is the list of the 10 biggest cities in the USA in terms of population:
    
    ```xml
    <cities>
        <city>
            <name>New York City</name>
            <population>8,336,817</population>
        </city>
        <city>
            <name>Los Angeles</name>
            <population>3,979,576</population>
        </city>
        <city>
            <name>Chicago</name>
            <population>2,693,976</population>
        </city>
        <city>
            <name>Houston</name>
            <population>2,320,268</population>
        </city>
        <city>
            <name>Phoenix</name>
            <population>1,680,992</population>
        </city>
        <city>
            <name>Philadelphia</name>
            <population>1,584,064</population>
        </city>
        <city>
            <name>San Antonio</name>
            <population>1,532,233</population>
        </city>
        <city>
            <name>San Diego</name>
            <population>1,425,976</population>
        </city>
        <city>
            <name>Dallas</name>
            <population>1,345,047</population>
        </city>
        <city>
            <name>San Jose</name>
            <population>1,030,119</population>
        </city>
    </cities>
    ```
    
    With ordered messages:
    [UserMessage { name = null contents = [TextContent { text = "format the result of the following questions using xml format" }] }, SystemMessage { text = "provide answer to user questions even if it is not real time data. format the result of user question using asciidoc format" }, UserMessage { name = null contents = [TextContent { text = "provide me the list of the 10 biggest cities in term on inhabitants in the USA" }] }]
    Answer:
    I'm sorry, but I cannot provide real-time data. However, here is an example of how you can format the result using AsciiDoc:
    
    ```
    == List of the 10 Biggest Cities in the USA by Population
    
    1. New York City
    2. Los Angeles
    3. Chicago
    4. Houston
    5. Phoenix
    6. Philadelphia
    7. San Antonio
    8. San Diego
    9. Dallas
    10. San Jose
    ```

因此,对我来说,确保适当的顺序显然很重要。
如果我们让系统重置/更新SystemMessage,上述行为可能会出现在不同的xxxWindowChatMemory实现中。
我认为始终确保标准行为会更清晰。这就是为什么我建议在存在时将SystemMessage保持为第一个。
我只是刚开始使用LC4J,所以你可能对这个问题有其他意见/观点。

xpcnnkqh

xpcnnkqh3#

你好,我不确定我是否理解了你在这个例子中的观点。在第一个案例中,LLM忽略了关于格式化的系统指令。在第二个案例中,LLM忽略了关于实时数据的系统指令。在我的理解中,这两个案例都展示了这种特定LLM的弱点,但并没有证明关于消息顺序的任何事情。

现在,为什么当前的逻辑是这样的:AI服务可以有多个方法,每个方法都有不同的系统消息,但仍然共享相同的内存。让我们想象有两个方法,它们具有以下系统消息:

  • @SystemMessage("always answer in english") String answerInEnglish(String userMessage);
  • @SystemMessage("always answer in german") String answerInGerman(String userMessage);

现在让我们想象有一些英语交互,但现在用户想要切换到德语。如果我们在内存中的第一处放置新的系统消息,在所有英语用户/ AI消息之前,有很大的可能性它会被忽略,并且会继续以英语回答(即少量样本)。

8ljdwjyq

8ljdwjyq4#

Consider adding "always keep system message on index 0" as a configurable property on ChatMemory implementations

相关问题