langchain使用自定義example?selector示例解析
簡介
在之前的文章中,我們提到了可以在跟大模型交互的時(shí)候,給大模型提供一些具體的例子內(nèi)容,方便大模型從這些內(nèi)容中獲取想要的答案。這種方便的機(jī)制在langchain中叫做FewShotPromptTemplate。
如果例子內(nèi)容少的話,其實(shí)無所謂,我們可以把所有的例子都發(fā)送給大語言模型進(jìn)行處理。
但是如果例子太多的話,每次都發(fā)送如此多的內(nèi)容,會(huì)讓我們的錢包承受不住。畢竟那些第三方的大語言模型是按token收費(fèi)的。
怎么辦呢? 能不能找到一個(gè)經(jīng)濟(jì)又有效的方法來完成我們的工作呢?
答案就是使用example selector。
使用和自定義example selector
我們回想一下在使用FewShotPromptTemplate的時(shí)候,實(shí)際上是可以同時(shí)傳入example_selector和examples。
prompt = FewShotPromptTemplate(
example_selector=example_selector,
example_prompt=example_prompt,
suffix="Question: {input}",
input_variables=["input"]
)這里我們使用了一個(gè)example_selector,那么什么是example_selector呢?
從名字上看他的主要作用就是從給定的examples中選擇需要的examples出來,提供給大模型使用,從而減少會(huì)話的token數(shù)目。
langchain中提供了這樣的example_selector的實(shí)現(xiàn),我們先來看下它的基礎(chǔ)類的定義是怎么樣的:
class BaseExampleSelector(ABC):
"""Interface for selecting examples to include in prompts."""
@abstractmethod
def add_example(self, example: Dict[str, str]) -> Any:
"""Add new example to store for a key."""
@abstractmethod
def select_examples(self, input_variables: Dict[str, str]) -> List[dict]:
"""Select which examples to use based on the inputs."""可以看到BaseExampleSelector繼承自ABC,并且定義了兩個(gè)需要實(shí)現(xiàn)的抽象方法。
一個(gè)方法叫做add_example。目的是向selector中添加一個(gè)example。
一個(gè)方法叫做select_examples,主要目的就是根據(jù)input,從examples中找出要select出來的內(nèi)容。
那么什么是ABC呢?
ABC當(dāng)然就是你了解到的ABC,但是他還有一些額外的含義。ABC的全稱叫做Abstract Base Class,也叫做抽象基類。主要用于在Python程序中創(chuàng)建抽象基類。
他提供了一些@abstractmethod,@abstarctproperty這些裝飾方法,來表明具體類的特征。
所以,如果我們想自定義一個(gè)ExampleSelector,只需要繼承自BaseExampleSelector,然后實(shí)現(xiàn)這兩個(gè)抽象方法即可。
langchain中的ExampleSelector實(shí)現(xiàn)
除了自定義實(shí)現(xiàn)之外,langchain已經(jīng)為我們提供了幾個(gè)常用的ExampleSelector實(shí)現(xiàn),一起來看看吧。
LengthBasedExampleSelector
LengthBasedExampleSelector是根據(jù)example的長度來進(jìn)行選擇的選擇器。
我們看下它的具體實(shí)現(xiàn):
def add_example(self, example: Dict[str, str]) -> None:
"""Add new example to list."""
self.examples.append(example)
string_example = self.example_prompt.format(**example)
self.example_text_lengths.append(self.get_text_length(string_example))add_example的邏輯是先把example添加到examples這個(gè)list中。
然后使用example_prompt對example進(jìn)行格式化,得到最終的輸出。
最后再把最后輸出的text長度添加到example_text_lengths數(shù)組中。
def select_examples(self, input_variables: Dict[str, str]) -> List[dict]:
"""Select which examples to use based on the input lengths."""
inputs = " ".join(input_variables.values())
remaining_length = self.max_length - self.get_text_length(inputs)
i = 0
examples = []
while remaining_length > 0 and i < len(self.examples):
new_length = remaining_length - self.example_text_lengths[i]
if new_length < 0:
break
else:
examples.append(self.examples[i])
remaining_length = new_length
i += 1
return examplesselect_examples方法實(shí)際上就是用max_length減去輸入text的長度,然后再去匹配example_text的長度,匹配一個(gè)減去一個(gè),最終得到特定長度的examples。
這個(gè)selector的最主要作用就是防止耗盡context window。因?yàn)閷τ诖蠖鄶?shù)大語言模型來說,用戶的輸入是有長度限制的。
如果超出了輸入長度,會(huì)產(chǎn)生意想不到的結(jié)果。
這個(gè)selector使用起來很簡單,下面是具體的例子:
examples = [
{"input": "happy", "output": "sad"},
{"input": "tall", "output": "short"},
{"input": "energetic", "output": "lethargic"},
{"input": "sunny", "output": "gloomy"},
{"input": "windy", "output": "calm"},
example_prompt = PromptTemplate(
input_variables=["input", "output"],
template="Input: {input}\nOutput: {output}",
)
example_selector = LengthBasedExampleSelector(
examples=examples,
example_prompt=example_prompt,
max_length=25,
)SemanticSimilarityExampleSelector和MaxMarginalRelevanceExampleSelector
這兩個(gè)selector是根據(jù)相似度來進(jìn)行example的查找的。
其中MaxMarginalRelevanceExampleSelector是SemanticSimilarityExampleSelector的字類,他是對SemanticSimilarityExampleSelector進(jìn)行了一些算法上的優(yōu)化。所以這里我們把他們兩個(gè)放在一起介紹。
這兩個(gè)selector和之前介紹的selector有所不同。因?yàn)樗麄冇玫搅讼蛄繑?shù)據(jù)庫。
向量數(shù)據(jù)庫是干什么用的呢?它的主要目的是把輸入轉(zhuǎn)換成各種向量然后存儲(chǔ)起來。向量數(shù)據(jù)庫可以方便的進(jìn)行輸入相識度的計(jì)算。
我們先來看下他們的add_example方法:
def add_example(self, example: Dict[str, str]) -> str:
"""Add new example to vectorstore."""
if self.input_keys:
string_example = " ".join(
sorted_values({key: example[key] for key in self.input_keys})
)
else:
string_example = " ".join(sorted_values(example))
ids = self.vectorstore.add_texts([string_example], metadatas=[example])
return ids[0]這個(gè)方法先把example的key加入到input_keys中,然后進(jìn)行排序。最后通過調(diào)用vectorstore的add_texts,把key和value加入到向量數(shù)據(jù)庫中。
這兩個(gè)selector的add_example都是一樣的。只有select_examples的方法不同。
其中SemanticSimilarityExampleSelector調(diào)用了vectorstore的similarity_search方法來實(shí)現(xiàn)相似度的搜索。
而MaxMarginalRelevanceExampleSelector則是調(diào)用vectorstore的max_marginal_relevance_search方法來實(shí)現(xiàn)搜索的。
兩者的搜索算法不太一樣。
因?yàn)槭褂昧讼蛄繑?shù)據(jù)庫,所以他們的調(diào)用方法和其他的也不太一樣:
examples = [
{"input": "happy", "output": "sad"},
{"input": "tall", "output": "short"},
{"input": "energetic", "output": "lethargic"},
{"input": "sunny", "output": "gloomy"},
{"input": "windy", "output": "calm"},
]
example_selector = SemanticSimilarityExampleSelector.from_examples(
examples,
# 使用的ebeddings
OpenAIEmbeddings(),
# 向量數(shù)據(jù)庫
Chroma,
# 要返回的數(shù)目
k=1
)NGramOverlapExampleSelector
最后一個(gè)要介紹的是NGramOverlapExampleSelector。這個(gè)selector使用的是ngram 重疊矩陣來選擇相似的輸入。
具體的實(shí)現(xiàn)算法和原理這里就不介紹了。大家有興趣的可以自行探索。
這個(gè)selector也不需要使用向量數(shù)據(jù)庫。
使用起來是這樣的:
example_selector = NGramOverlapExampleSelector(
examples=examples,
example_prompt=example_prompt,
threshold=-1.0,
)這里有個(gè)不太一樣的參數(shù)叫做threshold。
對于負(fù)閾值:Selector按ngram重疊分?jǐn)?shù)對示例進(jìn)行排序,不排除任何示例。
對于大于1.0的閾值:選擇器排除所有示例,并返回一個(gè)空列表。
對于等于0.0的閾值:選擇器根據(jù)ngram重疊分?jǐn)?shù)對示例進(jìn)行排序,并且排除與輸入沒有ngram重疊的那些。
總結(jié)
有了這些selector我們就可以在提供的examples中進(jìn)行特定的選擇,然后再把選擇的結(jié)果輸入給大語言模型。從而有效的減少token的浪費(fèi)。
以上就是langchain使用自定義example selector示例解析的詳細(xì)內(nèi)容,更多關(guān)于langchain自定義example selector的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python3實(shí)現(xiàn)常見的排序算法(示例代碼)
排序是非常常見的排序算法,今天給大家分享幾種比較常見的排序算法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-07-07
python中np.zeros_like函數(shù)用法詳解
這篇文章主要介紹了python中np.zeros_like函數(shù)用法的相關(guān)資料,np.zeros_like是?NumPy?庫中的一個(gè)函數(shù),用于創(chuàng)建一個(gè)與給定數(shù)組形狀和類型相同的新數(shù)組,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-04-04
Python辦公自動(dòng)化處理的10大場景應(yīng)用示例
這篇文章主要為大家介紹了Python辦公自動(dòng)化處理的10大場景應(yīng)用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Python爬取商家聯(lián)系電話以及各種數(shù)據(jù)的方法
今天小編就為大家分享一篇Python爬取商家聯(lián)系電話以及各種數(shù)據(jù)的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-11-11
提升Python Web應(yīng)用性能的10個(gè)關(guān)鍵技巧
Python作為一種強(qiáng)大的編程語言,在Web開發(fā)領(lǐng)域也有著廣泛的應(yīng)用,通過結(jié)合Python的靈活性和一些高性能的框架和工具,我們可以構(gòu)建出高性能的Web應(yīng)用程序,本文將介紹一些關(guān)鍵的技術(shù)和方法,幫助你在Python環(huán)境下構(gòu)建高性能的Web應(yīng)用程序,需要的朋友可以參考下2024-07-07
Pygame實(shí)戰(zhàn)練習(xí)之紙牌21點(diǎn)游戲
21點(diǎn)想必是很多人童年時(shí)期的經(jīng)典游戲,我們依舊能記得抱個(gè)老人機(jī)娛樂的場景,下面這篇文章主要給大家介紹了關(guān)于如何利用python寫一個(gè)簡單的21點(diǎn)小游戲的相關(guān)資料,需要的朋友可以參考下2021-09-09
Python如何解決secure_filename對中文不支持問題
最近使用到了secure_filename,然后悲劇的發(fā)現(xiàn)中文居然不展示出來,本文就詳細(xì)的介紹一下解決方法,感興趣的可以了解一下2021-07-07

