LangChain —— Message —— How to trim messages

文章目录

  • 一、概述
  • 二、获取最后的 max_tokens 令牌
  • 三、获取第一个 max_tokens 令牌
  • 四、编写自定义令牌计数器
  • 五、连成链
  • 六、使用 ChatMessageHistory


一、概述

 所有模型都有 有限的 上下文窗口,这意味着它们可以作为输入的 token 数量是有限的。如果你有很长的消息,或者一个 chain 或 agent 累积了很长的 历史消息,你需要管理你传递给模型的消息的长度。
 trim_messages util 提供了一些基本策略,用于将消息列表修剪为特定的 token 长度。


二、获取最后的 max_tokens 令牌

 为了获取消息列表中的最后一个 max_tokens,我们可以设置 strategy=“last”。请注意,对于我们的 token_counter,我们可以将其传入到一个函数 (下面将详细介绍) 或一个语言模型 (因为语言模型有一个消息令牌计数方法) 中。当调整消息以适应特定模型的上下文窗口时,将其传入到模型是有意义的:

# pip install -U langchain-openai
from langchain_core.messages import (AIMessage,HumanMessage,SystemMessage,trim_messages,
)
from langchain_openai import ChatOpenAImessages = [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"),
]trim_messages(messages,max_tokens=45,strategy="last",token_counter=ChatOpenAI(model="gpt-4o"),
)

 如果我们想始终保留初始系统消息,我们可以指定 include_system=True:
 如果我们想允许拆分消息的内容,我们可以指定 allow_partial=True:
 如果我们需要确保我们的第一条消息 (不包括 SystemMessage) 始终是特定类型的,我们可以指定 start_on:

trim_messages(messages,max_tokens=60,strategy="last",token_counter=ChatOpenAI(model="gpt-4o"),include_system=True,start_on="human",
)

三、获取第一个 max_tokens 令牌

 我们可以通过指定 strategy=“first” 来执行获取第一个 max_tokens 的翻转操作:

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

四、编写自定义令牌计数器

 我们可以编写一个自定义令牌计数器函数,该函数接收消息列表并返回一个整数。

from typing import List
# pip install tiktoken
import tiktoken
from langchain_core.messages import BaseMessage, ToolMessagedef str_token_counter(text: str) -> int:enc = tiktoken.get_encoding("o200k_base")return len(enc.encode(text))def tiktoken_counter(messages: List[BaseMessage]) -> int:"""Approximately reproduce https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynbFor simplicity only supports str Message.contents."""num_tokens = 3  # every reply is primed with <|start|>assistant<|message|>tokens_per_message = 3tokens_per_name = 1for msg in messages:if isinstance(msg, HumanMessage):role = "user"elif isinstance(msg, AIMessage):role = "assistant"elif isinstance(msg, ToolMessage):role = "tool"elif isinstance(msg, SystemMessage):role = "system"else:raise ValueError(f"Unsupported messages type {msg.__class__}")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_tokenstrim_messages(messages,max_tokens=45,strategy="last",token_counter=tiktoken_counter,
)
  • 定义 str_token_counter 函数
    • 该函数接受一个字符串 text 并返回该字符串的令牌数量。
    • 使用 tiktoken.get_encoding(“o200k_base”) 获取编码器,然后使用 enc.encode(text) 将文本编码为令牌,并返回令牌的长度。
  • 定义 tiktoken_counter 函数:
    • 该函数接受一个 BaseMessage 类型的消息列表 messages 并返回总的令牌数量。
    • 由于每个回复都以 <|start|>assistance<|message|> 开头,所以每个消息列表初始都默认有 3 个 token,每个消息有一个基本的令牌数 tokens_per_message,每个 name 属性预设的固定令牌数 tokens_per_name,假设其值为 1。
    • 函数通过迭代消息列表,并根据消息的角色 (如 user、assistant、tool、system) 计算令牌数量。
    • 根据消息的 tokens_per_message、role、content,计算总的令牌数。
    • 如果遇到不支持的消息类型,会引发 ValueError。
    • 对于每个消息,如果消息对象 msg 有 name 属性 (即 msg.name 不为 None 或空),那么就要计算该 name 属性所包含的令牌数量,并将其加入到总令牌数 num_tokens 中。
  • 调用 trim_messages 函数 (假设定义在其他地方):
    • messages:要处理的消息列表。
    • max_tokens=45:最大允许的令牌数。
    • strategy=“last”:修剪策略 (假设修剪最后的消息)。
    • token_counter=tiktoken_counter:用于计算令牌数的函数。

五、连成链

 trim_message可以以命令式(如上所述)或声明式的方式使用,从而便于与链中的其他组件组合。

llm = ChatOpenAI(model="gpt-4o")# Notice we don't pass in messages. This creates
# a RunnableLambda that takes messages as input
trimmer = trim_messages(max_tokens=45,strategy="last",token_counter=llm,include_system=True,
)chain = trimmer | llm
chain.invoke(messages)

 查看 LangSmith 跟踪,我们可以看到,在消息传递到模型之前,它们首先被修剪。
 如果只看 trimer,我们可以看到它是一个Runnable对象,可以像所有Runnables一样被调用:

trimmer.invoke(messages)

六、使用 ChatMessageHistory

 在处理聊天历史记录时,修剪消息特别有用,因为聊天历史记录可能会变得任意长:

from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistorychat_history = InMemoryChatMessageHistory(messages=messages[:-1])def dummy_get_session_history(session_id):if session_id != "1":return InMemoryChatMessageHistory()return chat_historyllm = ChatOpenAI(model="gpt-4o")trimmer = trim_messages(max_tokens=45,strategy="last",token_counter=llm,include_system=True,
)chain = trimmer | llm
chain_with_history = RunnableWithMessageHistory(chain, dummy_get_session_history)
chain_with_history.invoke([HumanMessage("what do you call a speechless parrot")],config={"configurable": {"session_id": "1"}},
)

 查看 LangSmith 跟踪,我们可以看到我们检索了所有消息,但在将消息传递给模型之前,它们被修剪成只有系统消息和最后一条人类消息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/45805.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言——数组、sizeof关键字

一、数组 1.数组的引入与定义&#xff1a; C语言中的数组是一种基本的数据结构&#xff0c;用于在计算机内存中连续存储相同类型的数据。数组中的每个元素可以通过索引来访问&#xff0c;索引通常是一个整数&#xff0c;用于指定元素在数组中的位置。在C语言中&#xff0c;数…

北京服装学院学报-自然科学版

《北京服装学院学报》&#xff08;自然科学版&#xff09;创立于1981年&#xff0c;是由北京市教委主管、北京服装学院主办的自然科学类学术期刊&#xff08;国际刊号&#xff1a;ISSN1001-0564,国内刊号&#xff1a;CN11-2523/TS&#xff09;。学报为季刊&#xff0c;每年3、6…

【香橙派】Orange pi AIpro开发板评测,看小白如何从0到1快速入门,以及亲测手写数字识别模型训练与推理

作为业界首款基于昇腾深度研发的AI开发板&#xff0c;Orange Pi AIpro无论在外观上、性能上还是技术服务支持上都非常优秀。 接口丰富&#xff0c;扩展能力强。支持Ubuntu、openEuler操作系统&#xff0c;满足大多数AI算法原型验证、推理应用开发的需求。 目录 开发板介绍亮点顶…

【C++】C++中的友元函数详解

目录 一.友元函数介绍 二.友元函数的使用场景 三.友元函数的注意事项 一.友元函数介绍 友元函数&#xff08;Friend Function&#xff09;是C中的一个特殊概念&#xff0c;它允许非成员函数访问类的私有&#xff08;private&#xff09;和保护&#xff08;protected&#x…

Laravel生成二维码图片

Laravel生成二维码图片 composer下载组件 https://github.com/SimpleSoftwareIO/simple-qrcode/tree/develop/docs/zh-cn composer require simplesoftwareio/simple-qrcode "~2"namespace App\Http\Controllers;use SimpleSoftwareIO\QrCode\Facades\QrCode;cla…

《代理选择与反爬虫策略探究:如何优化网络爬虫效率与稳定性》

代理IP如何选以及常见反爬策略 为什么需要代理&#xff1f; 因为有的网站会封IP&#xff0c;用户如果没有登录&#xff0c;那IP就是身份标识&#xff0c;如果网站发现用户行为异常就非常可能封IP 什么是代理IP 就是让一个人帮你转交请求&#xff0c;帮你转交的人对面不熟&a…

【机器学习】线性判别分析(LDA):从理论到实践

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 线性判别分析&#xff08;LDA&#xff09;&#xff1a;从理论到实践LDA的基本概…

c++ - 多态

文章目录 一、多态的概念二、多态使用三、多态的原理 一、多态的概念 1、概念&#xff1a; 多态就是具有多种形态&#xff0c;可以理解为同一个行为不同对象去完成表现出不同的状态&#xff0c;如&#xff1a; 二、多态使用 1、构成多态的条件 &#xff08;1&#xff09;派…

SpringCloud01_技术选型、生态底层、整合knife4j - swagger3、支付模块、订单模块、热部署Devtools(开发阶段)

文章目录 ①. 从Boot和Cloud版本选型②. SpringCloud生态底层③. 整合knife4j - swagger3④. 父工程项目搭建⑤. 支付微服务 - 8001⑥. 订单微服务 - consumer80⑦. 热部署Devtools(开发阶段)⑧. 测试Run DashBord ①. 从Boot和Cloud版本选型 ①. 结论:本次Java、cloud、boot…

程序的控制结构——switch语句【互三互三】

文章目录 &#x1f341; 引言 &#x1f341;1.语句格式&#xff1a; &#x1f341;2.语句执行过程 &#x1f341;3.语句格式举例 &#x1f341;例题 &#x1f449;【例1】 &#x1f680;示例代码 &#x1f449;【例2】 &#x1f680;【分析】 &#x1f680;示例代码…

【企业级监控】Zabbix实现邮箱报警

Zabbix监控自动化 文章目录 Zabbix监控自动化资源列表基础环境前言四、Zabbix邮件告警4.1、实现报警所需的条件4.1.1、告警媒介4.1.2、触发器&#xff08;trigger&#xff09;4.1.3、动作&#xff08;action&#xff09; 4.2、配置告警媒介4.2.1、设置告警媒介参数4.2.2、启用此…

卡码网KamaCoder 99. 岛屿数量

题目来源&#xff1a;99. 岛屿数量 C题解&#xff1a;来源代码随想录 懒得自己写了。直接搬运。。。 1. 深度优先搜索&#xff1a;它的循环在main函数里&#xff0c;遍历每个位置&#xff0c;判断 是否为陆地 及 是否访问过。 #include <iostream> #include <vecto…

docker 安装orcale11数据库

初次安装流程 1.拉取 oracle 11g 镜像&#xff08;有6g&#xff0c;要等较长的时间&#xff09;: docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g2.执行以下命令以创建并运行 Oracle 11g 容器&#xff08;其中&#xff1a;30026为映射主机端口&#xff0…

Python学习1---深浅拷贝

在Python中&#xff0c;当我们复制对象时&#xff0c;有两种主要的方式&#xff1a;深拷贝&#xff08;Deep Copy&#xff09;和浅拷贝&#xff08;Shallow Copy&#xff09;。 一、浅拷贝&#xff08;Shallow Copy&#xff09; 浅拷贝创建一个新对象&#xff0c;但是它包含的…

[1]从概念到实践:电商智能助手在AI Agent技术驱动下的落地实战案例深度剖析(AI Agent技术打造个性化、智能化的用户助手)

电商智能助手进化论:AI Agent技术引领下的智能化升级与实战效果评估 1.LLM Agent 的整体概述 1.0 Agent 在学术界的热度持续攀升 人工智能应用的几个阶段LLM Agent 的构成要素 语言模型 (LLM) 仅限于它们所训练的知识,并且这些知识很快就会过时。且 LLM 具备以下缺点: 会产…

PG大会周五于杭州举办;Pika发布4.0;阿里云MySQL上线Zero-ETL集成能力

重要更新 1. PostgreSQL中国技术大会举行12日&#xff08;周五&#xff09;于杭州举办&#xff0c;是PostgreSQL社区年度的大会&#xff0c;举办地点&#xff1a;杭州君尚云郦酒店&#xff08;杭州市上城区临丁路1188号&#xff09;&#xff0c;感兴趣的可以考虑现场参加 ( [1]…

【公益案例展】华为云X《无尽攀登》——攀登不停,向上而行

‍ 华为云公益案例 本项目案例由华为云投递并参与数据猿与上海大数据联盟联合推出的 #榜样的力量# 《2024中国数据智能产业最具社会责任感企业》榜单/奖项”评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 夏伯渝&#xff0c;中国无腿登珠峰第一人&#xff0c;一生43年…

Guava LocalCache源码分析:LocalCache生成

Guava LocalCache源码分析&#xff1a;Cache生成 版本LocalCache参数说明Cache构建过程LocalCache介绍LocalCache实例化将builder中的属性赋值到LocalCache中分段 LocalCache为guava本地缓存的解决方案&#xff0c;提供了基于容量&#xff0c;时间和引用的缓存回收方式&#xf…

目标检测大揭秘:算法种类与优劣分析

目标检测大揭秘&#xff1a;算法种类与优劣分析&#x1f50d; 在当今这个信息爆炸的时代&#xff0c;图像识别技术正逐渐成为我们生活中不可或缺的一部分。目标检测作为图像识别领域的重要分支&#xff0c;已经广泛应用于安全监控、自动驾驶、智能家居等多个领域。今天&#x…

算法复杂度<数据结构 C版>

什么是算法复杂度&#xff1f; 简单来说算法复杂度是用来衡量一个算法的优劣的&#xff0c;一个程序在运行时&#xff0c;对运行时间和运行空间有要求&#xff0c;即时间复杂度和空间复杂度。 目录 什么是算法复杂度&#xff1f; 大O的渐近表达式 时间复杂度示例 空间复杂度…