在 langchain 中使用自定义 example selector
简介
在之前的文章中,我们提到了可以在跟大模型交互的时候,给大模型提供一些具体的例子内容,方便大模型从这些内容中获取想要的答案。这种方便的机制在 langchain 中叫做 FewShotPromptTemplate。
如果例子内容少的话,其实无所谓,我们可以把所有的例子都发送给大语言模型进行处理。
但是如果例子太多的话,每次都发送如此多的内容,会让我们的钱包承受不住。毕竟那些第三方的大语言模型是按 token 收费的。
怎么办呢? 能不能找到一个经济又有效的方法来完成我们的工作呢?
答案就是使用 example selector。
使用和自定义 example selector
我们回想一下在使用 FewShotPromptTemplate 的时候,实际上是可以同时传入 example_selector 和 examples。
这里我们使用了一个 example_selector,那么什么是 example_selector 呢?
从名字上看他的主要作用就是从给定的 examples 中选择需要的 examples 出来,提供给大模型使用,从而减少会话的 token 数目。
langchain 中提供了这样的 example_selector 的实现,我们先来看下它的基础类的定义是怎么样的:
可以看到 BaseExampleSelector 继承自 ABC,并且定义了两个需要实现的抽象方法。
一个方法叫做 add_example。目的是向 selector 中添加一个 example。
一个方法叫做 select_examples,主要目的就是根据 input,从 examples 中找出要 select 出来的内容。
那么什么是 ABC 呢?
ABC 当然就是你了解到的 ABC,但是他还有一些额外的含义。ABC 的全称叫做 Abstract Base Class,也叫做抽象基类。主要用于在 Python 程序中创建抽象基类。
他提供了一些 @abstractmethod,@abstarctproperty 这些装饰方法,来表明具体类的特征。
所以,如果我们想自定义一个 ExampleSelector,只需要继承自 BaseExampleSelector,然后实现这两个抽象方法即可。
langchain 中的 ExampleSelector 实现
除了自定义实现之外,langchain 已经为我们提供了几个常用的 ExampleSelector 实现,一起来看看吧。
LengthBasedExampleSelector
LengthBasedExampleSelector 是根据 example 的长度来进行选择的选择器。
我们看下它的具体实现:
add_example 的逻辑是先把 example 添加到 examples 这个 list 中。
然后使用 example_prompt 对 example 进行格式化,得到最终的输出。
最后再把最后输出的 text 长度添加到 example_text_lengths 数组中。
select_examples 方法实际上就是用 max_length 减去输入 text 的长度,然后再去匹配 example_text 的长度,匹配一个减去一个,最终得到特定长度的 examples。
这个 selector 的最主要作用就是防止耗尽 context window。因为对于大多数大语言模型来说,用户的输入是有长度限制的。
如果超出了输入长度,会产生意想不到的结果。
这个 selector 使用起来很简单,下面是具体的例子:
SemanticSimilarityExampleSelector 和 MaxMarginalRelevanceExampleSelector
这两个 selector 是根据相似度来进行 example 的查找的。
其中 MaxMarginalRelevanceExampleSelector 是 SemanticSimilarityExampleSelector 的字类,他是对 SemanticSimilarityExampleSelector 进行了一些算法上的优化。所以这里我们把他们两个放在一起介绍。
这两个 selector 和之前介绍的 selector 有所不同。因为他们用到了向量数据库。
向量数据库是干什么用的呢?它的主要目的是把输入转换成各种向量然后存储起来。向量数据库可以方便的进行输入相识度的计算。
我们先来看下他们的 add_example 方法:
这个方法先把 example 的 key 加入到 input_keys 中,然后进行排序。最后通过调用 vectorstore 的 add_texts,把 key 和 value 加入到向量数据库中。
这两个 selector 的 add_example 都是一样的。只有 select_examples 的方法不同。
其中 SemanticSimilarityExampleSelector 调用了 vectorstore 的 similarity_search 方法来实现相似度的搜索。
而 MaxMarginalRelevanceExampleSelector 则是调用 vectorstore 的 max_marginal_relevance_search 方法来实现搜索的。
两者的搜索算法不太一样。
因为使用了向量数据库,所以他们的调用方法和其他的也不太一样:
NGramOverlapExampleSelector
最后一个要介绍的是 NGramOverlapExampleSelector。这个 selector 使用的是 ngram 重叠矩阵来选择相似的输入。
具体的实现算法和原理这里就不介绍了。大家有兴趣的可以自行探索。
这个 selector 也不需要使用向量数据库。
使用起来是这样的:
这里有个不太一样的参数叫做 threshold。
对于负阈值:Selector 按 ngram 重叠分数对示例进行排序,不排除任何示例。
对于大于 1.0 的阈值:选择器排除所有示例,并返回一个空列表。
对于等于 0.0 的阈值:选择器根据 ngram 重叠分数对示例进行排序,并且排除与输入没有 ngram 重叠的那些。
总结
有了这些 selector 我们就可以在提供的 examples 中进行特定的选择,然后再把选择的结果输入给大语言模型。
从而有效的减少 token 的浪费。
版权声明: 本文为 InfoQ 作者【程序那些事】的原创文章。
原文链接:【http://xie.infoq.cn/article/11935b56e829676e6fac83811】。文章转载请联系作者。
评论