**聊天历史太长?试试这个高效的消息修剪技巧!**

286 阅读3分钟

引言

随着聊天模型的流行,管理聊天历史变得愈发重要。无论是在开发聊天机器人还是应用智能代理,消息过长都可能导致性能问题。本文将介绍一种实用的技术:使用 trim_messages 函数来修剪消息长度,从而优化模型输入。这不仅可以提高效率,还能避免超出上下文窗口的限制。

主要内容

消息修剪的重要性

所有的AI模型都有一个上下文窗口限制,即它们能够处理的最大token数。如果消息历史过长,超出这个限制时可能会导致错误或性能下降。因此,掌握修剪技术对于持续提升模型的响应能力非常关键。

使用 trim_messages 工具

trim_messages 工具提供了一些基本策略,以保证消息列表不会超出指定的token长度。以下是一些常用策略以及如何实现:

获取最后的 max_tokens

当需要获取最后一部分消息时,可以使用策略 strategy="last"。这对于希望保持最近对话的上下文非常有帮助。

from langchain_core.messages import AIMessage, HumanMessage, SystemMessage, trim_messages
from langchain_openai import ChatOpenAI

messages = [
    SystemMessage("you're a good assistant, you always respond with a joke."),
    HumanMessage("i wonder why it's called langchain"),
    AIMessage("Well, I guess they thought 'WordRope' and 'SentenceString' just didn't have the same ring to it!"),
    HumanMessage("and who is harrison chasing anyways"),
    AIMessage("Hmmm let me think.\n\nWhy, he's probably chasing after the last cup of coffee in the office!"),
    HumanMessage("what do you call a speechless parrot"),
]

# 使用API代理服务提高访问稳定性
trimmed_messages = trim_messages(
    messages,
    max_tokens=45,
    strategy="last",
    token_counter=ChatOpenAI(model="gpt-4o"),
)

保持系统消息

在某些场景下,我们可能希望始终保留初始系统消息,可以通过 include_system=True 实现。

trimmed_messages = trim_messages(
    messages,
    max_tokens=45,
    strategy="last",
    token_counter=ChatOpenAI(model="gpt-4o"),
    include_system=True,
)

获取最初的 max_tokens

相反地,如果只需要获取最初的部分消息,可以通过 strategy="first" 达到目的。

trimmed_messages = trim_messages(
    messages,
    max_tokens=45,
    strategy="first",
    token_counter=ChatOpenAI(model="gpt-4o"),
)

代码示例

以下代码展示了如何使用自定义token计数器函数:

from typing import List
import tiktoken
from langchain_core.messages import BaseMessage

def str_token_counter(text: str) -> int:
    enc = tiktoken.get_encoding("o200k_base")
    return len(enc.encode(text))

def tiktoken_counter(messages: List[BaseMessage]) -> int:
    num_tokens = 3
    tokens_per_message = 3
    tokens_per_name = 1
    for msg in messages:
        role = ("user", "assistant", "tool", "system")[["HumanMessage", "AIMessage", "ToolMessage", "SystemMessage"].index(msg.__class__.__name__)]
        num_tokens += tokens_per_message + str_token_counter(role) + str_token_counter(msg.content)
        if msg.name:
            num_tokens += tokens_per_name + str_token_counter(msg.name)
    return num_tokens

trimmed_messages = trim_messages(
    messages,
    max_tokens=45,
    strategy="last",
    token_counter=tiktoken_counter,
)

常见问题和解决方案

  • 如何处理超长的消息? 可使用 allow_partial=True 允许拆分消息内容。

  • 网络请求失败怎么办? 由于某些地区网络限制,建议使用 API 代理服务来提高访问稳定性。

总结和进一步学习资源

掌握消息修剪技术不仅能提高模型的效率,还能确保合适的上下文传递。了解更多关于 langchain 的内容,推荐访问 Langchain官方文档

参考资料

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力! ---END---