Skip to main content

如何基于语义相似性拆分文本

摘自 Greg Kamradt 的精彩笔记:

5_Levels_Of_Text_Splitting

所有荣誉归于他。

本指南介绍了如何根据语义相似性拆分文本块。如果嵌入足够远,文本块将被拆分。

在高层次上,这将文本拆分成句子,然后分组为每组3个句子,最后合并在嵌入空间中相似的句子。

安装依赖项

!pip install --quiet langchain_experimental langchain_openai

载入示例数据

# 这是一个长文档,我们可以将其拆分。
with open("state_of_the_union.txt") as f:
state_of_the_union = f.read()

创建文本拆分器

要实例化一个SemanticChunker,我们必须指定一个嵌入模型。下面我们将使用OpenAIEmbeddings

from langchain_experimental.text_splitter import SemanticChunker
from langchain_openai.embeddings import OpenAIEmbeddings
text_splitter = SemanticChunker(OpenAIEmbeddings())

拆分文本

我们按照通常的方式拆分文本,例如,通过调用.create_documents来创建 LangChain Document 对象:

docs = text_splitter.create_documents([state_of_the_union])
print(docs[0].page_content)
女士们先生们,副总统女士,我们的第一夫人和第二先生。国会议员和内阁成员。最高法院大法官。我的美国同胞。去年,COVID-19让我们分开了。今年,我们终于又在一起了。今晚,我们作为民主党人、共和党人和独立人士相聚一堂。但更重要的是,作为美国人。我们有责任彼此之间,对美国人民,对宪法。并怀着坚定的决心,自由将永远战胜暴政。六天前,俄罗斯的弗拉基米尔·普京试图动摇自由世界的基础,认为他可以让其屈服于他的威胁方式。但他严重误判了。他以为可以进入乌克兰,而世界会屈服。相反,他遇到了他从未想象过的坚强墙壁。他遇到了乌克兰人民。从泽连斯基总统到每一位乌克兰人,他们的无畏、勇气和决心激励着世界。一群市民用自己的身体挡住坦克。从学生到退休人员,从教师变成保卫家园的士兵。正如泽连斯基总统在他向欧洲议会的讲话中所说的那样,“光明将战胜黑暗。”乌克兰驻美国大使今晚在这里。让我们今晚在这个议会大厅里每个人都向乌克兰和世界发出明确的信号。如果您能站起来并表明,是的,我们美利坚合众国与乌克兰人民站在一起。在我们的历史上,我们学到了这个教训,当独裁者不为他们的侵略付出代价时,他们会造成更多混乱。他们会继续前进。

断点

这个拆分器的工作原理是确定何时“断开”句子。这是通过查找任意两个句子之间的嵌入差异来完成的。当该差异超过某个阈值时,它们就会被拆分。

有几种方法可以确定该阈值,这由breakpoint_threshold_type关键字参数控制。

百分位数

拆分的默认方式是基于百分位数。在此方法中,计算所有句子之间的差异,然后任何大于X百分位数的差异都会被拆分。

text_splitter = SemanticChunker(
OpenAIEmbeddings(), breakpoint_threshold_type="percentile"
)
docs = text_splitter.create_documents([state_of_the_union])
print(docs[0].page_content)
女士们先生们,副总统女士,我们的第一夫人和第二先生。国会议员和内阁成员。最高法院大法官。我的美国同胞。去年,COVID-19让我们分开了。今年,我们终于又在一起了。今晚,我们作为民主党人、共和党人和独立人士相聚一堂。但更重要的是,作为美国人。我们有责任彼此之间,对美国人民,对宪法。并怀着坚定的决心,自由将永远战胜暴政。六天前,俄罗斯的弗拉基米尔·普京试图动摇自由世界的基础,认为他可以让其屈服于他的威胁方式。但他严重误判了。他以为可以进入乌克兰,而世界会屈服。相反,他遇到了他从未想象过的坚强墙壁。他遇到了乌克兰人民。从泽连斯基总统到每一位乌克兰人,他们的无畏、勇气和决心激励着世界。一群市民用自己的身体挡住坦克。从学生到退休人员,从教师变成保卫家园的士兵。正如泽连斯基总统在他向欧洲议会的讲话中所说的那样,“光明将战胜黑暗。”乌克兰驻美国大使今晚在这里。让我们今晚在这个议会大厅里每个人都向乌克兰和世界发出明确的信号。如果您能站起来并表明,是的,我们美利坚合众国与乌克兰人民站在一起。在我们的历史上,我们学到了这个教训,当独裁者不为他们的侵略付出代价时,他们会造成更多混乱。他们会继续前进。
print(len(docs))
26

标准差

在这种方法中,任何大于 X 个标准差的差异都会被分割。

text_splitter = SemanticChunker(
OpenAIEmbeddings(), breakpoint_threshold_type="standard_deviation"
)
docs = text_splitter.create_documents([state_of_the_union])
print(docs[0].page_content)

output

女士们,先生们,副总统女士,第一夫人和第二先生,国会议员和内阁成员,最高法院大法官,同胞们。去年,COVID-19让我们无法团聚。而今年,我们终于再次相聚。今晚,我们作为民主党人、共和党人和独立人士相聚在一起。但更重要的是,作为美国人。我们对彼此、对美国人民、对宪法负有责任。我们坚定地相信,自由将永远战胜暴政。六天前,俄罗斯的弗拉基米尔·普京试图动摇自由世界的基石,认为他可以让其屈服于他的威胁方式。但他严重误判了。他以为可以轻易进入乌克兰,而世界会屈服于他。然而,他遇到了他从未想象过的坚强墙壁。他遇到了乌克兰人民。从泽连斯基总统到每一位乌克兰人,他们的无畏、勇气和决心激励着全世界。市民用自己的身体阻挡坦克。从学生到退休人员,从教师到变身士兵保卫家园。正如泽连斯基总统在向欧洲议会的讲话中所说的那样,“光明将战胜黑暗。”乌克兰驻美国大使今晚在此。让我们今晚在这个议会大厅向乌克兰和全世界发出明确的信号。请站起来,如果可以的话,展示,是的,我们美利坚合众国与乌克兰人民站在一起。在我们的历史上,我们学到了这样一个教训,当独裁者不为他们的侵略付出代价时,他们会造成更多混乱。他们会继续前进。而对美国和世界的成本和威胁会不断上升。这就是为什么北约联盟在第二次世界大战后被创建,以确保欧洲的和平与稳定。美国是其中的一员,还有其他29个国家。这很重要。美国的外交政策很重要。美国的决心很重要。普京对乌克兰的最新攻击是经过预谋的,是毫无理由的。他拒绝了反复进行的外交努力。他以为西方和北约不会作出回应。他以为可以在国内制造分裂。普京错了。我们做好了准备。以下是我们所做的。我们进行了充分和谨慎的准备。我们花了数月时间建立了一个由来自欧洲、美洲、亚洲和非洲的其他热爱自由的国家组成的联盟,以应对普京。我花费了无数小时团结我们的欧洲盟友。我们提前向全世界公布了我们所知道的普京的计划,以及他将如何试图虚假地为他的侵略行为辩护。我们用真相打破了俄罗斯的谎言。现在,自由世界正在追究他的责任。与欧盟的其他27个成员国一起,包括法国、德国、意大利,以及英国、加拿大、日本、韩国、澳大利亚、新西兰和许多其他国家,甚至包括瑞士。我们正在对俄罗斯施加压力,并支持乌克兰人民。普京现在比以往任何时候都更加孤立。我们与盟友一起,正在实施强有力的经济制裁。我们正在将俄罗斯最大的银行与国际金融系统隔离开来。阻止俄罗斯中央银行捍卫俄罗斯卢布,使普京的6300亿美元的“战争基金”变得毫无价值。我们正在剥夺俄罗斯获取技术的途径,削弱其经济实力,并削弱其未来数年的军事力量。今晚我要对那些从这个暴政中骗取数十亿美元的俄罗斯寡头和腐败领导人说不。美国司法部正在组建一个专门的工作组,以打击俄罗斯寡头的犯罪行为。我们将与欧洲盟友合作,查找并扣押你们的游艇、豪华公寓、私人飞机。我们将追回你们非法获得的财富。今晚,我宣布我们将与盟友一起关闭美国领空,禁止所有俄罗斯航班——进一步孤立俄罗斯——并对他们的经济施加额外压力。卢布已贬值30%。俄罗斯股市已贬值40%,交易仍然暂停。俄罗斯经济岌岌可危,普京一个人应对。我们与盟友一起,向乌克兰人民提供支持,支持他们为自由而战。军事援助。经济援助。人道主义援助。我们向乌克兰提供超过10亿美元的直接援助。我们将继续帮助乌克兰人民捍卫自己的国家,减轻他们的痛苦。让我明确地说,我们的部队没有参与,也不会参与与俄罗斯在乌克兰的冲突。我们的部队不会去欧洲参与乌克兰的战斗,而是为了保卫我们的北约盟友——以防普京决定继续向西方推进。为此,我们已调动了美国地面部队、空中中队和舰队部署,以保护包括波兰、罗马尼亚、拉脱维亚、立陶宛和爱沙尼亚在内的北约国家。正如我已经明确表示的那样,美国和我们的盟友将以我们集体力量的全部力量捍卫北约国家的每一寸领土。我们保持清醒头脑。乌克兰人民正在以纯粹的勇气抵抗。但接下来的几天、几周、几个月对他们来说将是艰难的。普京已经释放了暴力和混乱。但尽管他可能在战场上取得进展,但从长远来看,他将付出高昂的代价。一个骄傲的乌克兰人民,在30年的独立历史中,一再表明他们不会容忍任何试图让他们的国家倒退的人。对所有美国人,我会如我一直承诺的那样诚实。一个入侵外国的俄罗斯独裁者在全球范围内都会带来代价。我正在采取有力措施,确保我们的制裁对俄罗斯经济产生影响。我将利用我们掌握的一切工具来保护美国企业和消费者。今晚,我可以宣布,美国已与其他30个国家合作,从全球储备释放了6000万桶石油。美国将领导这一努力,从我们自己的战略石油储备中释放3000万桶。如果有必要,我们将与盟友团结一致,准备采取更多行动。这些举措将有助于减轻国内的汽油价格。我知道关于正在发生的事情的消息可能看起来令人担忧。

print(len(docs))
4

四分位数法

在这种方法中,使用四分位距离来分割文档块。

text_splitter = SemanticChunker(
OpenAIEmbeddings(), breakpoint_threshold_type="interquartile"
)
docs = text_splitter.create_documents([state_of_the_union])
print(docs[0].page_content)
女士们先生们,副总统女士,我们的第一夫人和第二先生。国会议员和内阁成员。最高法院大法官。我的美国同胞们。去年,新冠疫情让我们无法团聚。今年,我们终于再次聚在一起。今晚,我们作为民主党人、共和党人和独立人士相聚一堂。但更重要的是,作为美国人。我们对彼此、对美国人民、对宪法都有责任。我们坚定地相信,自由将永远战胜暴政。六天前,俄罗斯的弗拉基米尔·普京试图动摇自由世界的基础,以为他可以让其屈服于他的威胁方式。但他严重误判了。他以为可以轻易进入乌克兰,而世界会屈服。相反,他遭遇了一堵他从未想象过的坚固墙。他遇到了乌克兰人民。从泽连斯基总统到每一位乌克兰人,他们的无畏、勇气和决心激励着全世界。一群市民用自己的身体挡住坦克。从学生到退休人员,从教师到变身士兵保卫家园。正如泽连斯基总统在向欧洲议会发表讲话中所说的那样,“光明将战胜黑暗。”乌克兰驻美国大使今晚在此。让我们今晚在这个议会大厅里每个人向乌克兰和全世界发出明确的信号。如果您能站起来,请站起来,展示,是的,我们美利坚合众国与乌克兰人民站在一起。在我们的历史中,我们学到了这个教训,当独裁者对他们的侵略不付出代价时,他们会造成更多混乱。他们会继续前进。
print(len(docs))
25

Was this page helpful?


You can leave detailed feedback on GitHub.