国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

一文入門最熱的LLM應用開發(fā)框架LangChain

這篇具有很好參考價值的文章主要介紹了一文入門最熱的LLM應用開發(fā)框架LangChain。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一文入門最熱的LLM應用開發(fā)框架LangChain

在人工智能領(lǐng)域的不斷發(fā)展中,語言模型扮演著重要的角色。特別是大型語言模型(LLM),如 ChatGPT,已經(jīng)成為科技領(lǐng)域的熱門話題,并受到廣泛認可。
在這個背景下,LangChain 作為一個以 LLM 模型為核心的開發(fā)框架出現(xiàn),為自然語言處理開啟了一個充滿可能性的世界。
借助 LangChain,我們可以創(chuàng)建各種應用程序,包括聊天機器人和智能問答工具。

1.?LangChain 簡介

1.1. LangChain 發(fā)展史

LangChain 的作者是 Harrison Chase,最初是于 2022 年 10 月開源的一個項目,在 GitHub 上獲得大量關(guān)注之后迅速轉(zhuǎn)變?yōu)橐患页鮿?chuàng)公司。2017 年 Harrison Chase 還在哈佛上大學,如今已是硅谷的一家熱門初創(chuàng)公司的 CEO,這對他來說是一次重大而迅速的躍遷。Insider 獨家報道,人工智能初創(chuàng)公司 LangChain 在種子輪一周后,再次獲得紅杉領(lǐng)投的 2000 萬至 2500 萬美元融資,估值達到 2 億美元。

一文入門最熱的LLM應用開發(fā)框架LangChain

1.2.LangChain 為什么這么火

LangChain 目前是有兩個語言版本(python 和 nodejs),從下圖可以看出來,短短半年的時間該項目的 python 版本已經(jīng)獲得了 54k+的 star。nodejs 版本也在短短 4 個月收貨了 7k+的 star,這無疑利好前端同學,不需要會 python 也能快速上手 LLM 應用開發(fā)。

一文入門最熱的LLM應用開發(fā)框架LangChain

筆者認為 Langchain 作為一個大語言模型應用開發(fā)框架,解決了現(xiàn)在開發(fā)人工智能應用的一些切實痛點。以 GPT 模型為例:

1.數(shù)據(jù)滯后,現(xiàn)在訓練的數(shù)據(jù)是到 2021 年 9 月。

2.token 數(shù)量限制,如果讓它對一個 300 頁的 pdf 進行總結(jié),直接使用則無能為力。

3.不能進行聯(lián)網(wǎng),獲取不到最新的內(nèi)容。

4.不能與其他數(shù)據(jù)源鏈接。

另外作為一個膠水層框架,極大地提高了開發(fā)效率,它的作用可以類比于 jquery 在前端開發(fā)中的角色,使得開發(fā)者可以更專注于創(chuàng)新和優(yōu)化產(chǎn)品功能。

1.3. LLM 應用架構(gòu)

LangChian 作為一個大語言模型開發(fā)框架,是 LLM 應用架構(gòu)的重要一環(huán)。那什么是 LLM 應用架構(gòu)呢?其實就是指基于語言模型的應用程序設(shè)計和開發(fā)的架構(gòu)。

LangChian 可以將 LLM 模型、向量數(shù)據(jù)庫、交互層 Prompt、外部知識、外部工具整合到一起,進而可以自由構(gòu)建 LLM 應用。

?

2. LangChain 組件

一文入門最熱的LLM應用開發(fā)框架LangChain

如上圖,LangChain 包含六部分組成,分別為:Models、Prompts、Indexes、Memory、Chains、Agents。

2.1.Models(模型)

下面我們以具體示例分別闡述下 Chat Modals, Embeddings, LLMs。

2.1.1. 聊天模型

LangChain 為使用聊天模型提供了一個標準接口。聊天模型是語言模型的一種變體。雖然聊天模型在內(nèi)部使用語言模型,但它們所提供的接口略有不同。它們不是暴露一個 "輸入文本,輸出文本" 的 API,而是提供了一個以 "聊天消息" 作為輸入和輸出的接口。

聊天模型的接口是基于消息而不是原始文本。LangChain 目前支持的消息類型有 AIMessage、HumanMessage、SystemMessage 和 ChatMessage,其中 ChatMessage 接受一個任意的角色參數(shù)。大多數(shù)情況下,您只需要處理 HumanMessage、AIMessage 和 SystemMessage。

#?導入OpenAI的聊天模型,及消息類型
from?langchain.chat_models?import?ChatOpenAI
from?langchain.schema?import?(
????AIMessage,
????HumanMessage,
????SystemMessage
)

#?初始化聊天對象
chat?=?ChatOpenAI(openai_api_key="...")

#?向聊天模型發(fā)問
chat([HumanMessage(content="Translate?this?sentence?from?English?to?French:?I?love?programming.")])

OpenAI 聊天模式支持多個消息作為輸入。這是一個系統(tǒng)和用戶消息聊天模式的例子:

messages?=?[
????SystemMessage(content="You?are?a?helpful?assistant?that?translates?English?to?French."),
????HumanMessage(content="I?love?programming.")
]
chat(messages)

當然也可以進行批量處理,批量輸出。

batch_messages?=?[
????[
????????SystemMessage(content="You?are?a?helpful?assistant?that?translates?English?to?French."),
????????HumanMessage(content="I?love?programming.")
????],
????[
????????SystemMessage(content="You?are?a?helpful?assistant?that?translates?English?to?French."),
????????HumanMessage(content="I?love?artificial?intelligence.")
????],
]
result?=?chat.generate(batch_messages)
result

上面介紹了聊天的角色處理以及如何進行批量處理消息。我們都知道向 openAI 調(diào)用接口都是要花錢的,如果用戶問同一個問題,對結(jié)果進行了緩存,這樣就可以減少接口的調(diào)用并且也能加快接口返回的速度。LangChain 也很貼心的提供了緩存的功能。并且提供了兩種緩存方案,內(nèi)存緩存方案和數(shù)據(jù)庫緩存方案,當然支持的數(shù)據(jù)庫緩存方案有很多種。

#?導入聊天模型,SQLiteCache模塊
import?os
os.environ["OPENAI_API_KEY"]?=?'your?apikey'
import?langchain
from?langchain.chat_models?import?ChatOpenAI
from?langchain.cache?import?SQLiteCache

#?設(shè)置語言模型的緩存數(shù)據(jù)存儲的地址
langchain.llm_cache?=?SQLiteCache(database_path=".langchain.db")

#?加載?llm?模型
llm?=?ChatOpenAI()

#?第一次向模型提問
result?=?llm.predict('tell?me?a?joke')
print(result)

#?第二次向模型提問同樣的問題
result2?=?llm.predict('tell?me?a?joke')
print(result2)

另外聊天模式也提供了一種流媒體回應。這意味著,而不是等待整個響應返回,你就可以開始處理它盡快。

2.1.2. 嵌入

這個更多的是用于文檔、文本或者大量數(shù)據(jù)的總結(jié)、問答場景,一般是和向量庫一起使用,實現(xiàn)向量匹配。其實就是把文本等內(nèi)容轉(zhuǎn)成多維數(shù)組,可以后續(xù)進行相似性的計算和檢索。他相比 fine-tuning 最大的優(yōu)勢就是,不用進行訓練,并且可以實時添加新的內(nèi)容,而不用加一次新的內(nèi)容就訓練一次,并且各方面成本要比 fine-tuning 低很多。

下面以代碼展示下 embeddings 是什么。

#?導入os,?設(shè)置環(huán)境變量,導入OpenAI的嵌入模型
import?os
from?langchain.embeddings.openai?import?OpenAIEmbeddings
os.environ["OPENAI_API_KEY"]?=?'your?apikey'

#?初始化嵌入模型
embeddings?=?OpenAIEmbeddings()

#?把文本通過嵌入模型向量化
res?=?embeddings.embed_query('hello?world')
/*
[
???-0.004845875,???0.004899438,??-0.016358767,??-0.024475135,?-0.017341806,
????0.012571548,??-0.019156644,???0.009036391,??-0.010227379,?-0.026945334,
????0.022861943,???0.010321903,??-0.023479493,?-0.0066544134,??0.007977734,
???0.0026371893,???0.025206111,??-0.012048521,???0.012943339,??0.013094575,
???-0.010580265,??-0.003509951,???0.004070787,???0.008639394,?-0.020631202,
??-0.0019203906,???0.012161949,??-0.019194454,???0.030373365,?-0.031028723,
???0.0036170771,??-0.007813894,?-0.0060778237,??-0.017820721,?0.0048647798,
???-0.015640393,???0.001373733,??-0.015552171,???0.019534737,?-0.016169721,
????0.007316074,???0.008273906,???0.011418369,???-0.01390117,?-0.033347685,
????0.011248227,??0.0042503807,??-0.012792102,?-0.0014595914,??0.028356876,
????0.025407761,?0.00076445413,??-0.016308354,???0.017455231,?-0.016396577,
????0.008557475,???-0.03312083,???0.031104341,???0.032389853,??-0.02132437,
????0.003324056,??0.0055610985,?-0.0078012915,???0.006090427,?0.0062038545,
??...?1466?more?items
]
*/

下圖是 LangChain 兩種語言包支持的 embeddings。

一文入門最熱的LLM應用開發(fā)框架LangChain
2.1.3. 大語言模型

LLMS 是 LangChain 的核心,從官網(wǎng)可以看到 LangChain 繼承了非常多的大語言模型。

一文入門最熱的LLM應用開發(fā)框架LangChain

2.2. Prompts(提示詞)

2.2.1. Prompt Templates

LangChain 提供了 PromptTemplates,允許你可以根據(jù)用戶輸入動態(tài)地更改提示,如果你有編程基礎(chǔ),這應該對你來說很簡單。當用戶需要輸入多個類似的 prompt 時,生成一個 prompt 模板是一個很好的解決方案,可以節(jié)省用戶的時間和精力。下面是一個示例,將 LLM 作為一個給新開商店命名的顧問,用戶只需告訴 LLM 商店的主要特點,它將返回 10 個新開商店的名字。

from?langchain.llms?import?OpenAI

#?定義生成商店的方法
def?generate_store_names(store_features):
????prompt_template?=?"我正在開一家新的商店,它的主要特點是{}。請幫我想出10個商店的名字。"
????prompt?=?prompt_template.format(store_features)

????llm?=?OpenAI()
????response?=?llm.generate(prompt,?max_tokens=10,?temperature=0.8)

????store_names?=?[gen[0].text.strip()?for?gen?in?response.generations]
????return?store_names

store_features?=?"時尚、創(chuàng)意、獨特"

store_names?=?generate_store_names(store_features)
print(store_names)

這樣,用戶只需告訴 LLM 商店的主要特點,就可以獲得 10 個新開商店的名字,而無需重復輸入類似的 prompt 內(nèi)容。另外LangChainHub包含了許多可以通過 LangChain 直接加載的 Prompt Templates。順便我們也可以通過學習他們的 Prompt 設(shè)計來給我們以啟發(fā)。

2.2.2. Few-shot example

Few-shot examples 是一組可用于幫助語言模型生成更好響應的示例。

要生成具有 few-shot examples 的 prompt,可以使用 FewShotPromptTemplate。該類接受一個 PromptTemplate 和一組 few-shot examples。然后,它使用這些 few-shot examples 格式化 prompt 模板。

我們再看一個例子,需求是根據(jù)用戶輸入,讓模型返回對應的反義詞,我們要通過示例來告訴模型什么是反義詞, 這就是 few-shot examples(小樣本提示)。

import?os
os.environ["OPENAI_API_KEY"]?=?'your?apikey'
from?langchain?import?PromptTemplate,?FewShotPromptTemplate
from?langchain.llms?import?OpenAI

examples?=?[
????{"word":?"黑",?"antonym":?"白"},
????{"word":?"傷心",?"antonym":?"開心"},
]

example_template?=?"""
單詞:?{word}
反義詞:?{antonym}\\n
"""

#?創(chuàng)建提示詞模版
example_prompt?=?PromptTemplate(
????input_variables=["word",?"antonym"],
????template=example_template,
)

#?創(chuàng)建小樣本提示詞模版
few_shot_prompt?=?FewShotPromptTemplate(
????examples=examples,
????example_prompt=example_prompt,
????prefix="給出每個單詞的反義詞",
????suffix="單詞:?{input}\\n反義詞:",
????input_variables=["input"],
????example_separator="\\n",
)

#?格式化小樣本提示詞
prompt_text?=?few_shot_prompt.format(input="粗")

#?調(diào)用OpenAI
llm?=?OpenAI(temperature=0.9)

print(llm(prompt_text))
2.2.3. Example Selector

如果你有大量的示例,則可以使用 ExampleSelector 來選擇最有信息量的一些示例,以幫助你生成更可能產(chǎn)生良好響應的提示。接下來,我們將使用 LengthBasedExampleSelector,根據(jù)輸入的長度選擇示例。當你擔心構(gòu)造的提示將超過上下文窗口的長度時,此方法非常有用。對于較長的輸入,它會選擇包含較少示例的提示,而對于較短的輸入,它會選擇包含更多示例。

import?os
os.environ["OPENAI_API_KEY"]?=?'your?apikey'
from?langchain.prompts?import?PromptTemplate,?FewShotPromptTemplate
from?langchain.prompts.example_selector?import?LengthBasedExampleSelector
from?langchain.prompts.example_selector?import?LengthBasedExampleSelector


#?These?are?a?lot?of?examples?of?a?pretend?task?of?creating?antonyms.
examples?=?[
????{"word":?"happy",?"antonym":?"sad"},
????{"word":?"tall",?"antonym":?"short"},
????{"word":?"energetic",?"antonym":?"lethargic"},
????{"word":?"sunny",?"antonym":?"gloomy"},
????{"word":?"windy",?"antonym":?"calm"},
]
#?例子格式化模版
example_formatter_template?=?"""
Word:?{word}
Antonym:?{antonym}\n
"""
example_prompt?=?PromptTemplate(
????input_variables=["word",?"antonym"],
????template=example_formatter_template,
)

#?使用?LengthBasedExampleSelector來選擇例子
example_selector?=?LengthBasedExampleSelector(
????examples=examples,
????example_prompt=example_prompt,
????#?最大長度
????max_length=25,
)

#?使用'example_selector'創(chuàng)建小樣本提示詞模版
dynamic_prompt?=?FewShotPromptTemplate(
????example_selector=example_selector,
????example_prompt=example_prompt,
????prefix="Give?the?antonym?of?every?input",
????suffix="Word:?{input}\nAntonym:",
????input_variables=["input"],
????example_separator="\n\n",
)

longString?=?"big?and?huge?and?massive?and?large?and?gigantic?and?tall?and?much?much?much?much?much?bigger?than?everything?else"

print(dynamic_prompt.format(input=longString))

另外官方也提供了根據(jù)最大邊際相關(guān)性、文法重疊、語義相似性來選擇示例。

2.3. Indexes(索引)

索引是指對文檔進行結(jié)構(gòu)化的方法,以便 LLM 能夠更好的與之交互。該組件主要包括:Document Loaders(文檔加載器)、Text Splitters(文本拆分器)、VectorStores(向量存儲器)以及 Retrievers(檢索器)。

2.3.1. Document Loaders

指定源進行加載數(shù)據(jù)的。將特定格式的數(shù)據(jù),轉(zhuǎn)換為文本。如 CSV、File Directory、HTML、

JSON、Markdown、PDF。另外使用相關(guān)接口處理本地知識,或者在線知識。如 AirbyteJSON

Airtable、Alibaba Cloud MaxCompute、wikipedia、BiliBili、GitHub、GitBook 等等。

2.3.2. Text Splitters

由于模型對輸入的字符長度有限制,我們在碰到很長的文本時,需要把文本分割成多個小的文本片段。

文本分割最簡單的方式是按照字符長度進行分割,但是這會帶來很多問題,比如說如果文本是一段代碼,一個函數(shù)被分割到兩段之后就成了沒有意義的字符,所以整體的原則是把語義相關(guān)的文本片段放在一起。

LangChain 中最基本的文本分割器是 CharacterTextSplitter ,它按照指定的分隔符(默認“\n\n”)進行分割,并且考慮文本片段的最大長度。我們看個例子:

from?langchain.text_splitter?import?CharacterTextSplitter

#?初始字符串
state_of_the_union?=?"..."

text_splitter?=?CharacterTextSplitter(
????separator?=?"\\n\\n",
????chunk_size?=?1000,
????chunk_overlap??=?200,
????length_function?=?len,
)

texts?=?text_splitter.create_documents([state_of_the_union])

除了 CharacterTextSplitter 以外,LangChain 還支持多個高級文本分割器,如下:

一文入門最熱的LLM應用開發(fā)框架LangChain
2.3.3. VectorStores

存儲提取的文本向量,包括 Faiss、Milvus、Pinecone、Chroma 等。如下是 LangChain 集成的向量數(shù)據(jù)庫。

一文入門最熱的LLM應用開發(fā)框架LangChain
2.3.4. Retrievers

檢索器是一種便于模型查詢的存儲數(shù)據(jù)的方式,LangChain 約定檢索器組件至少有一個方法 get_relevant_texts,這個方法接收查詢字符串,返回一組文檔。下面是一個簡單的列子:

from?langchain.chains?import?RetrievalQA
from?langchain.llms?import?OpenAI
from?langchain.document_loaders?import?TextLoader
from?langchain.indexes?import?VectorstoreIndexCreator
loader?=?TextLoader('../state_of_the_union.txt',?encoding='utf8')

#?對加載的內(nèi)容進行索引
index?=?VectorstoreIndexCreator().from_loaders([loader])

query?=?"What?did?the?president?say?about?Ketanji?Brown?Jackson"

#?通過query的方式找到語義檢索的結(jié)果
index.query(query)

2.4. Chains(鏈)

鏈允許我們將多個組件組合在一起以創(chuàng)建一個單一的、連貫的任務(wù)。例如,我們可以創(chuàng)建一個鏈,它接受用戶輸入,使用 PromptTemplate 對其進行格式化,然后將格式化的響應傳遞給 LLM。另外我們也可以通過將多個鏈組合在一起,或者將鏈與其他組件組合來構(gòu)建更復雜的鏈。

2.4.1. LLMChain

LLMChain 是一個簡單的鏈,它圍繞語言模型添加了一些功能。它在整個 LangChain 中廣泛使用,包括在其他鏈和代理中。它接受一個提示模板,將其與用戶輸入進行格式化,并返回 LLM 的響應。

from?langchain?import?PromptTemplate,?OpenAI,?LLMChain

prompt_template?=?"What?is?a?good?name?for?a?company?that?makes?{product}?"

llm?=?OpenAI(temperature=0)
llm_chain?=?LLMChain(
????llm=llm,
????prompt=PromptTemplate.from_template(prompt_template)
)
llm_chain("colorful?socks")

除了所有 Chain 對象共享的call和 run 方法外,LLMChain 還提供了一些調(diào)用得方法,如下是不同調(diào)用方法的說明.

●?call方法返回輸入和輸出鍵值。

另外可以通過將 return_only_outputs 設(shè)置為 True,可以將其配置為只返回輸出鍵值。

llm_chain("corny",?return_only_outputs=True)
????{'text':?'Why?did?the?tomato?turn?red??Because?it?saw?the?salad?dressing!'}

● run 方法返回的是字符串而不是字典。

llm_chain.run({"adjective":?"corny"})
????'Why?did?the?tomato?turn?red??Because?it?saw?the?salad?dressing!'

● apply 方法允許你對一個輸入列表進行調(diào)用

input_list?=?[
????{"product":?"socks"},
????{"product":?"computer"},
????{"product":?"shoes"}
]

llm_chain.apply(input_list)
????[{'text':?'\n\nSocktastic!'},
?????{'text':?'\n\nTechCore?Solutions.'},
?????{'text':?'\n\nFootwear?Factory.'}]

● generate 方法類似于 apply 方法,但它返回的是 LLMResult 而不是字符串。LLMResult 通常包含有用的生成信息,例如令牌使用情況和完成原因。

llm_chain.generate(input_list)
????LLMResult(generations=[[Generation(text='\n\nSocktastic!',?generation_info={'finish_reason':?'stop',?'logprobs':?None})],?[Generation(text='\n\nTechCore?Solutions.',?generation_info={'finish_reason':?'stop',?'logprobs':?None})],?[Generation(text='\n\nFootwear?Factory.',?generation_info={'finish_reason':?'stop',?'logprobs':?None})]],?llm_output={'token_usage':?{'prompt_tokens':?36,?'total_tokens':?55,?'completion_tokens':?19},?'model_name':?'text-davinci-003'})

● predict 方法類似于 run 方法,不同之處在于輸入鍵被指定為關(guān)鍵字參數(shù),而不是一個 Python 字典。

#?Single?input?example
llm_chain.predict(product="colorful?socks")
2.4.2. SimpleSequentialChain

順序鏈的最簡單形式,其中每個步驟都有一個單一的輸入/輸出,并且一個步驟的輸出是下一步的輸入。

一文入門最熱的LLM應用開發(fā)框架LangChain

如下就是將兩個 LLMChain 進行組合成順序鏈進行調(diào)用的案例。

from?langchain.llms?import?OpenAI
from?langchain.chains?import?LLMChain
from?langchain.prompts?import?PromptTemplate
from?langchain.chains?import?SimpleSequentialChain

#?定義第一個chain
llm?=?OpenAI(temperature=.7)
template?=?"""You?are?a?playwright.?Given?the?title?of?play,?it?is?your?job?to?write?a?synopsis?for?that?title.

Title:?{title}
Playwright:?This?is?a?synopsis?for?the?above?play:"""
prompt_template?=?PromptTemplate(input_variables=["title"],?template=template)
synopsis_chain?=?LLMChain(llm=llm,?prompt=prompt_template)

#?定義第二個chain

llm?=?OpenAI(temperature=.7)
template?=?"""You?are?a?play?critic?from?the?New?York?Times.?Given?the?synopsis?of?play,?it?is?your?job?to?write?a?review?for?that?play.

Play?Synopsis:
{synopsis}
Review?from?a?New?York?Times?play?critic?of?the?above?play:"""
prompt_template?=?PromptTemplate(input_variables=["synopsis"],?template=template)
review_chain?=?LLMChain(llm=llm,?prompt=prompt_template)

#?通過簡單順序鏈組合兩個LLMChain
overall_chain?=?SimpleSequentialChain(chains=[synopsis_chain,?review_chain],?verbose=True)

#?執(zhí)行順序鏈
review?=?overall_chain.run("Tragedy?at?sunset?on?the?beach")
2.4.3. SequentialChain

相比 SimpleSequentialChain 只允許有單個輸入輸出,它是一種更通用的順序鏈形式,允許多個輸入/輸出。

特別重要的是: 我們?nèi)绾蚊斎?輸出變量名稱。在上面的示例中,我們不必考慮這一點,因為我們只是將一個鏈的輸出直接作為輸入傳遞給下一個鏈,但在這里我們確實需要擔心這一點,因為我們有多個輸入。

第一個 LLMChain:

#?這是一個?LLMChain,根據(jù)戲劇的標題和設(shè)定的時代,生成一個簡介。
llm?=?OpenAI(temperature=.7)
template?=?"""You?are?a?playwright.?Given?the?title?of?play?and?the?era?it?is?set?in,?it?is?your?job?to?write?a?synopsis?for?that?title.
#?這里定義了兩個輸入變量title和era,并定義一個輸出變量:synopsis
Title:?{title}
Era:?{era}
Playwright:?This?is?a?synopsis?for?the?above?play:"""
prompt_template?=?PromptTemplate(input_variables=["title",?"era"],?template=template)
synopsis_chain?=?LLMChain(llm=llm,?prompt=prompt_template,?output_key="synopsis")

第二個 LLMChain:

#?這是一個?LLMChain,根據(jù)劇情簡介撰寫一篇戲劇評論。
llm?=?OpenAI(temperature=.7)
template?=?"""You?are?a?play?critic?from?the?New?York?Times.?Given?the?synopsis?of?play,?it?is?your?job?to?write?a?review?for?that?play.
#?定義了一個輸入變量:synopsis,輸出變量:review
Play?Synopsis:
{synopsis}
Review?from?a?New?York?Times?play?critic?of?the?above?play:"""
prompt_template?=?PromptTemplate(input_variables=["synopsis"],?template=template)
review_chain?=?LLMChain(llm=llm,?prompt=prompt_template,?output_key="review")

執(zhí)行順序鏈:

overall_chain({"title":"Tragedy?at?sunset?on?the?beach",?"era":?"Victorian?England"})

執(zhí)行結(jié)果,可以看到會把每一步的輸出都能打印出來。

????>?Entering?new?SequentialChain?chain...

????>?Finished?chain.

????{'title':?'Tragedy?at?sunset?on?the?beach',
?????'era':?'Victorian?England',
?????'synopsis':?"xxxxxx",
?????'review':?"xxxxxxx"}
2.4.4. TransformChain

轉(zhuǎn)換鏈允許我們創(chuàng)建一個自定義的轉(zhuǎn)換函數(shù)來處理輸入,將處理后的結(jié)果用作下一個鏈的輸入。如下示例我們將創(chuàng)建一個轉(zhuǎn)換函數(shù),它接受超長文本,將文本過濾為僅前 3 段,然后將其傳遞到 LLMChain 中以總結(jié)這些內(nèi)容。

from?langchain.chains?import?TransformChain,?LLMChain,?SimpleSequentialChain
from?langchain.llms?import?OpenAI
from?langchain.prompts?import?PromptTemplate

#?模擬超長文本
with?open("../../state_of_the_union.txt")?as?f:
????state_of_the_union?=?f.read()

#?定義轉(zhuǎn)換方法,入?yún)⒑统鰠⒍际亲值?,取前三?def?transform_func(inputs:?dict)?->?dict:
????text?=?inputs["text"]
????shortened_text?=?"\n\n".join(text.split("\n\n")[:3])
????return?{"output_text":?shortened_text}

#?轉(zhuǎn)換鏈:輸入變量:text,輸出變量:output_text
transform_chain?=?TransformChain(
????input_variables=["text"],?output_variables=["output_text"],?transform=transform_func
)
#?prompt模板描述
template?=?"""Summarize?this?text:

{output_text}

Summary:"""
#?prompt模板
prompt?=?PromptTemplate(input_variables=["output_text"],?template=template)
#?llm鏈
llm_chain?=?LLMChain(llm=OpenAI(),?prompt=prompt)
#?使用順序鏈
sequential_chain?=?SimpleSequentialChain(chains=[transform_chain,?llm_chain])
#?開始執(zhí)行
sequential_chain.run(state_of_the_union)
#?結(jié)果
"""
????'?The?speaker?addresses?the?nation,?noting?that?while?last?year?they?were?kept?apart?due?to?COVID-19,?this?year?they?are?together?again.
????They?are?reminded?that?regardless?of?their?political?affiliations,?they?are?all?Americans.'

"""

2.5. Memory(記憶)

熟悉 openai 的都知道,openai 提供的聊天接口 api,本身是不具備“記憶的”能力。如果想要使聊天具有記憶功能,則需要我們自行維護聊天記錄,即每次把聊天記錄發(fā)給 gpt。具體過程如下

第一次發(fā)送:

import?openai

openai.ChatCompletion.create(
??model="gpt-3.5-turbo",
??messages=[
????????{"role":?"system",?"content":?"You?are?a?helpful?assistant."},
????????{"role":?"user",?"content":?"Hello"},
????]
)

第二次發(fā)送就要帶上我們第一次的記錄:

import?openai

openai.ChatCompletion.create(
??model="gpt-3.5-turbo",
??messages=[
????????{"role":?"system",?"content":?"You?are?a?helpful?assistant."},
????????{"role":?"user",?"content":?"Hello"},
????????{"role":?"assistant",?"content":?"Hello,?how?can?I?help?you?"},
????????{"role":?"user",?"content":?"who?is?more?stylish?Pikachu?or?Neo"},
????]
)

那如果我們一直聊天下去,發(fā)送的內(nèi)容也越來越多,那很可能就碰到 token 的限制。聰明的同學會發(fā)現(xiàn),其實我們只保留最近幾次的聊天記錄就可以了。沒錯,其實 LangChain 也是這樣實現(xiàn)的,不過 LangChain 提供了更多的方法。

langchain 提供了不同的 Memory 組件完成內(nèi)容記憶,如下是目前提供的組件。

2.5.1. ConversationBufferMemory

該組件類似我們上面的描述,只不過它會將聊天內(nèi)容記錄在內(nèi)存中,而不需要每次再手動拼接聊天記錄。

2.5.2. ConversationBufferWindowMemory

相比較第一個記憶組件,該組件增加了一個窗口參數(shù),會保存最近看 k 論的聊天內(nèi)容。

2.5.3. ConversationTokenBufferMemory

在內(nèi)存中保留最近交互的緩沖區(qū),并使用 token 長度而不是交互次數(shù)來確定何時刷新交互。

2.5.4. ConversationSummaryMemory

相比第一個記憶組件,該組件只會存儲一個用戶和機器人之間的聊天內(nèi)容的摘要。

2.5.5. ConversationSummaryBufferMemory

結(jié)合了上面兩個思路,存儲一個用戶和機器人之間的聊天內(nèi)容的摘要并使用 token 長度來確定何時刷新交互。

2.5.6. VectorStoreRetrieverMemory

它是將所有之前的對話通過向量的方式存儲到 VectorDB(向量數(shù)據(jù)庫)中,在每一輪新的對話中,會根據(jù)用戶的輸入信息,匹配向量數(shù)據(jù)庫中最相似的 K 組對話。

2.6. Agents(代理)

一些應用程序需要根據(jù)用戶輸入靈活地調(diào)用 LLM 和其他工具的鏈。代理接口為這樣的應用程序提供了靈活性。代理可以訪問一套工具,并根據(jù)用戶輸入確定要使用哪些工具。我們可以簡單的理解為他可以動態(tài)的幫我們選擇和調(diào)用 chain 或者已有的工具。代理主要有兩種類型 Action agents 和 Plan-and-execute agents。

2.6.1. Action agents

行為代理: 在每個時間步,使用所有先前動作的輸出來決定下一個動作。下圖展示了行為代理執(zhí)行的流程。

一文入門最熱的LLM應用開發(fā)框架LangChain
2.6.2. Plan-and-execute agents

預先決定完整的操作順序,然后執(zhí)行所有操作而不更新計劃,下面是其流程。

● 接收用戶輸入

● 計劃要采取的完整步驟順序

● 按順序執(zhí)行步驟,將過去步驟的輸出作為未來步驟的輸入傳遞

?

3. LangChain 實戰(zhàn)

3.1. 完成一次問答

LangChain 加載 OpenAI 的模型,并且完成一次問答。

先設(shè)置我們的 openai 的 key,然后,我們進行導入和執(zhí)行。

#?導入os,?設(shè)置環(huán)境變量,導入OpenAI模型
import?os
os.environ["OPENAI_API_KEY"]?=?'你的api?key'
from?langchain.llms?import?OpenAI

#?加載?OpenAI?模型,并指定模型名字
llm?=?OpenAI(model_name="text-davinci-003",max_tokens=1024)

#?向模型提問
result?=?llm("怎么評價人工智能")

3.2. 通過谷歌搜索并返回答案

為了實現(xiàn)我們的項目,我們需要使用 Serpapi 提供的 Google 搜索 API 接口。首先,我們需要在 Serpapi 官網(wǎng)上注冊一個用戶,并復制由 Serpapi 生成的 API 密鑰。接下來,我們需要將這個 API 密鑰設(shè)置為環(huán)境變量,就像我們之前設(shè)置 OpenAI API 密鑰一樣。

#?導入os,?設(shè)置環(huán)境變量
import?os
os.environ["OPENAI_API_KEY"]?=?'你的api?key'
os.environ["SERPAPI_API_KEY"]?=?'你的api?key'

然后,開始編寫我的代碼。

#?導入加載工具、初始化代理、代理類型及OpenAI模型
from?langchain.agents?import?load_tools
from?langchain.agents?import?initialize_agent
from?langchain.agents?import?AgentType
from?langchain.llms?import?OpenAI

#?加載?OpenAI?模型
llm?=?OpenAI(temperature=0)

#?加載?serpapi、語言模型的數(shù)學工具
tools?=?load_tools(["serpapi",?"llm-math"],?llm=llm)

#?工具加載后都需要初始化,verbose?參數(shù)為?True,會打印全部的執(zhí)行詳情
agent?=?initialize_agent(tools,?llm,?agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,?verbose=True)

#?執(zhí)行代理
agent.run("今天是幾號?歷史上的今天發(fā)生了什么事情")

可以看到,正確的返回了日期(有時差),并且返回了歷史上的今天。并且通過設(shè)置 verbose 這個參數(shù)為 True,可以看到完整的 chain 執(zhí)行過程。將我們的問題拆分成了幾個步驟,然后一步一步得到最終的答案。

3.3. 對超長文本進行總結(jié)

假如我們想要用 openai api 對一個段文本進行總結(jié),我們通常的做法就是直接發(fā)給 api 讓他總結(jié)。但是如果文本超過了 api 最大的 token 限制就會報錯。這時,我們一般會進行對文章進行分段,比如通過 tiktoken 計算并分割,然后將各段發(fā)送給 api 進行總結(jié),最后將各段的總結(jié)再進行一個全部的總結(jié)。

LangChain 很好的幫我們處理了這個過程,使得我們編寫代碼變的非常簡單。

#?導入os,設(shè)置環(huán)境變量。導入文本加載器、總結(jié)鏈、文本分割器及OpenAI模型
import?os
os.environ["OPENAI_API_KEY"]?=?'你的api?key'
from?langchain.document_loaders?import?TextLoader
from?langchain.chains.summarize?import?load_summarize_chain
from?langchain.text_splitter?import?RecursiveCharacterTextSplitter
from?langchain?import?OpenAI

#?獲取當前腳本所在的目錄
base_dir?=?os.path.dirname(os.path.abspath(__file__))

#?構(gòu)建doc.txt文件的路徑
doc_path?=?os.path.join(base_dir,?'static',?'open.txt')

#?通過文本加載器加載文本
loader?=?TextLoader(doc_path)

#?將文本轉(zhuǎn)成?Document?對象
document?=?loader.load()

#?初始化文本分割器
text_splitter?=?RecursiveCharacterTextSplitter(
????chunk_size?=?800,
????chunk_overlap?=?0
)

#?切分文本
split_documents?=?text_splitter.split_documents(document)

#?加載?llm?模型
llm?=?OpenAI(model_name="text-davinci-003",?max_tokens=1500)

#?創(chuàng)建總結(jié)鏈
chain?=?load_summarize_chain(llm,?chain_type="refine",?verbose=True)

#?執(zhí)行總結(jié)鏈
chain.run(split_documents)

這里解釋下文本分割器的 chunk_overlap 參數(shù)和 chain 的 chain_type 參數(shù)。

chunk_overlap 是指切割后的每個 document 里包含幾個上一個 document 結(jié)尾的內(nèi)容,主要作用是為了增加每個 document 的上下文關(guān)聯(lián)。比如,chunk_overlap=0 時, 第一個 document 為 aaaaaa,第二個為 bbbbbb;當 chunk_overlap=2 時,第一個 document 為 aaaaaa,第二個為 aabbbbbb。

chain_type 主要控制了將 document 傳遞給 llm 模型的方式,一共有 4 種方式:

stuff: 這種最簡單粗暴,會把所有的 document 一次全部傳給 llm 模型進行總結(jié)。如果 document 很多的話,勢必會報超出最大 token 限制的錯,所以總結(jié)文本的時候一般不會選中這個。

map_reduce: 這個方式會先將每個 document 進行總結(jié),最后將所有 document 總結(jié)出的結(jié)果再進行一次總結(jié)。

一文入門最熱的LLM應用開發(fā)框架LangChain

refine: 這種方式會先總結(jié)第一個 document,然后在將第一個 document 總結(jié)出的內(nèi)容和第二個 document 一起發(fā)給 llm 模型在進行總結(jié),以此類推。這種方式的好處就是在總結(jié)后一個 document 的時候,會帶著前一個的 document 進行總結(jié),給需要總結(jié)的 document 添加了上下文,增加了總結(jié)內(nèi)容的連貫性。

map_rerank: 這種一般不會用在總結(jié)的 chain 上,而是會用在問答的 chain 上,他其實是一種搜索答案的匹配方式。首先你要給出一個問題,他會根據(jù)問題給每個 document 計算一個這個 document 能回答這個問題的概率分數(shù),然后找到分數(shù)最高的那個 document ,在通過把這個 document 轉(zhuǎn)化為問題的 prompt 的一部分(問題+document)發(fā)送給 llm 模型,最后 llm 模型返回具體答案。

3.4. 構(gòu)建本地知識庫問答機器人

通過這個可以很方便的做一個可以介紹公司業(yè)務(wù)的機器人,或是介紹一個產(chǎn)品的機器人。這里主要使用了 Embedding(相關(guān)性)的能力。

```
導入os,設(shè)置環(huán)境變量。導入OpenAI嵌入模型、Chroma向量數(shù)據(jù)庫、文本分割器、OpenAI模型、向量數(shù)據(jù)庫數(shù)據(jù)查詢模塊及文件夾文檔加載器
```

import?os
os.environ["OPENAI_API_KEY"]?=?'你的api?key'
from?langchain.embeddings.openai?import?OpenAIEmbeddings
from?langchain.vectorstores?import?Chroma
from?langchain.text_splitter?import?CharacterTextSplitter
from?langchain?import?OpenAI,VectorDBQA
from?langchain.document_loaders?import?DirectoryLoader

#?獲取當前腳本所在的目錄
base_dir?=?os.path.dirname(os.path.abspath(__file__))

#?構(gòu)建doc.txt文件的路徑
doc_Directory?=?os.path.join(base_dir,?'static')

#?加載文件夾中的所有txt類型的文件
loader?=?DirectoryLoader(doc_Directory,?glob='**/*.txt')

#?將數(shù)據(jù)轉(zhuǎn)成?document?對象,每個文件會作為一個?document
documents?=?loader.load()

#?初始化加載器
text_splitter?=?CharacterTextSplitter(chunk_size=100,?chunk_overlap=0)

#?切割加載的?document
split_docs?=?text_splitter.split_documents(documents)

#?初始化?openai?的?embeddings?對象
embeddings?=?OpenAIEmbeddings()

#?將?document?通過?openai?的?embeddings?對象計算?embedding?向量信息并臨時存入?Chroma?向量數(shù)據(jù)庫,用于后續(xù)匹配查詢
docsearch?=?Chroma.from_documents(split_docs,?embeddings)

#?創(chuàng)建問答對象
qa?=?VectorDBQA.from_chain_type(llm=OpenAI(),?chain_type="stuff",?vectorstore=docsearch,return_source_documents=True)

#?進行問答
result?=?qa({"query":?"一年收入是多少?"})

上圖中成功的從我們的給到的數(shù)據(jù)中獲取了正確的答案。

3.5.構(gòu)建向量索引數(shù)據(jù)庫

?? Home | Chroma

我們上個案例里面有一步是將 document 信息轉(zhuǎn)換成向量信息和 embeddings 的信息并臨時存入 Chroma 數(shù)據(jù)庫。

因為是臨時存入,所以當我們上面的代碼執(zhí)行完成后,上面的向量化后的數(shù)據(jù)將會丟失。如果想下次使用,那么就還需要再計算一次 embeddings,這肯定不是我們想要的。 LangChain 支持的數(shù)據(jù)庫有很多,這個案例介紹下通過 Chroma 個數(shù)據(jù)庫來講一下如何做向量數(shù)據(jù)持久化。

chroma 是個本地的向量數(shù)據(jù)庫,他提供的一個 persist_directory 來設(shè)置持久化目錄進行持久化。讀取時,只需要調(diào)取 from_document 方法加載即可。

from?langchain.vectorstores?import?Chroma

#?持久化數(shù)據(jù)
docsearch?=?Chroma.from_documents(documents,?embeddings,?persist_directory="D:/vector_store")
docsearch.persist()

#?從已有文件中加載數(shù)據(jù)
docsearch?=?Chroma(persist_directory="D:/vector_store",?embedding_function=embeddings)

3.6.基于 LangChain 構(gòu)建的開源應用

基于 LangChain 的優(yōu)秀項目資源庫

基于 LangChain 和 ChatGLM-6B 等系列 LLM 的針對本地知識庫的自動問答

?

4.?總結(jié)

隨著 LangChain 不斷迭代和優(yōu)化,它的功能將變得越來越強大,支持的范圍也將更廣泛。無論是處理復雜的語言模型還是解決各種實際問題,LangChain 都將展現(xiàn)出更高的實力和靈活性。然而,我必須承認,我的理解能力和解釋能力是有限的,可能會出現(xiàn)錯誤或者解釋不夠清晰。因此,懇請讀者們諒解。

5、參考文獻

●?LangChain | LangChain

●?LangChain 中文入門教程 - LangChain 的中文入門教程

?

作者: 騰訊應用寶 MoonWebTeam 團隊? jansezhou文章來源地址http://www.zghlxwxcb.cn/news/detail-710491.html

到了這里,關(guān)于一文入門最熱的LLM應用開發(fā)框架LangChain的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Util應用框架 UI 開發(fā)快速入門

    Util應用框架 UI 開發(fā)快速入門

    本文是Util應用框架 Angular UI 開發(fā)快速入門教程. Util 應用框架目前僅支持用于開發(fā)管理后臺的 UI. 本文介紹了 Util UI 的技術(shù)特點和功能支持. Js語言 TypeScript TypeScript 是 微軟開發(fā)的腳本語言, 擴展了弱類型的 Javascript,提供增強的語法和強類型支持. 為編輯器代碼提示和語法錯誤檢

    2024年02月08日
    瀏覽(19)
  • 基于LangChain的LLM應用開發(fā)3——記憶

    基于LangChain的LLM應用開發(fā)3——記憶

    此情可待成追憶,只是當時已惘然。我們?nèi)祟悤泻芏嗷蛎篮没蛲纯嗟幕貞?,有的回憶會漸漸模糊,有的回憶午夜夢醒,會浮上心頭。 然而現(xiàn)在的大語言模型都是沒有記憶的,都是無狀態(tài)的,大語言模型自身不會記住和你對話之間的歷史消息。根本用不著“時時勤拂拭”,天

    2024年02月08日
    瀏覽(64)
  • LangChain大型語言模型(LLM)應用開發(fā)(五):評估

    LangChain大型語言模型(LLM)應用開發(fā)(五):評估

    LangChain是一個基于大語言模型(如ChatGPT)用于構(gòu)建端到端語言模型應用的 Python 框架。它提供了一套工具、組件和接口,可簡化創(chuàng)建由大型語言模型 (LLM) 和聊天模型提供支持的應用程序的過程。LangChain 可以輕松管理與語言模型的交互,將多個組件鏈接在一起,以便在不同的

    2024年02月15日
    瀏覽(30)
  • LangChain大型語言模型(LLM)應用開發(fā)(三):Chains

    LangChain大型語言模型(LLM)應用開發(fā)(三):Chains

    LangChain是一個基于大語言模型(如ChatGPT)用于構(gòu)建端到端語言模型應用的 Python 框架。它提供了一套工具、組件和接口,可簡化創(chuàng)建由大型語言模型 (LLM) 和聊天模型提供支持的應用程序的過程。LangChain 可以輕松管理與語言模型的交互,將多個組件鏈接在一起,以便在不同的

    2024年02月12日
    瀏覽(20)
  • LangChain大型語言模型(LLM)應用開發(fā)(六):Agents

    LangChain大型語言模型(LLM)應用開發(fā)(六):Agents

    LangChain是一個基于大語言模型(如ChatGPT)用于構(gòu)建端到端語言模型應用的 Python 框架。它提供了一套工具、組件和接口,可簡化創(chuàng)建由大型語言模型 (LLM) 和聊天模型提供支持的應用程序的過程。LangChain 可以輕松管理與語言模型的交互,將多個組件鏈接在一起,以便在不同的

    2024年02月16日
    瀏覽(30)
  • 文心一言接入Promptulate,開發(fā)復雜LLM應用程序

    最近在嘗試將文心一言的LLM能力接入Promptulate,故寫了一篇博客記錄一下,Promptulate 是 Promptulate AI 旗下的大語言模型自動化與應用開發(fā)框架,旨在幫助開發(fā)者通過更小的成本構(gòu)建行業(yè)級的大模型應用,其包含了LLM領(lǐng)域應用層開發(fā)的大部分常用組件,如外部工具組件、模型組件

    2024年02月10日
    瀏覽(46)
  • LangChain大型語言模型(LLM)應用開發(fā)(四):Q&A over Documents

    LangChain大型語言模型(LLM)應用開發(fā)(四):Q&A over Documents

    LangChain是一個基于大語言模型(如ChatGPT)用于構(gòu)建端到端語言模型應用的 Python 框架。它提供了一套工具、組件和接口,可簡化創(chuàng)建由大型語言模型 (LLM) 和聊天模型提供支持的應用程序的過程。LangChain 可以輕松管理與語言模型的交互,將多個組件鏈接在一起,以便在不同的

    2024年02月16日
    瀏覽(62)
  • Dify開源大語言模型(LLM) 應用開發(fā)平臺如何使用Docker部署與遠程訪問

    Dify開源大語言模型(LLM) 應用開發(fā)平臺如何使用Docker部署與遠程訪問

    本文主要介紹如何在Linux Ubuntu系統(tǒng)以Docker的方式快速部署Dify,并結(jié)合cpolar內(nèi)網(wǎng)穿透工具實現(xiàn)公網(wǎng)遠程訪問本地Dify! Dify 是一款開源的大語言模型(LLM) 應用開發(fā)平臺。它融合了后端即服務(wù)(Backend as Service)和 LLMOps 的理念,使開發(fā)者可以快速搭建生產(chǎn)級的生成式 AI 應用。即使你

    2024年04月10日
    瀏覽(25)
  • 從零開發(fā)短視頻電商 Java開發(fā)者的AI大模型(LLM)應用開發(fā)和設(shè)計-LangChain4j

    從零開發(fā)短視頻電商 Java開發(fā)者的AI大模型(LLM)應用開發(fā)和設(shè)計-LangChain4j

    Github : https://github.com/langchain4j https://github.com/langchain4j/langchain4j https://github.com/langchain4j/langchain4j-embeddings https://github.com/langchain4j/langchain4j-examples Java版 langchain , 利用LLMs的力量增強你的java應用程序。 該項目的目標是簡化 AI/LLM 功能到 Java 應用程序的集成。 可以通過以下方式實

    2024年01月16日
    瀏覽(24)
  • LangChain大型語言模型(LLM)應用開發(fā)(一):Models, Prompts and Output Parsers

    LangChain大型語言模型(LLM)應用開發(fā)(一):Models, Prompts and Output Parsers

    LangChain是一個基于大語言模型(如ChatGPT)用于構(gòu)建端到端語言模型應用的 Python 框架。它提供了一套工具、組件和接口,可簡化創(chuàng)建由大型語言模型 (LLM) 和聊天模型提供支持的應用程序的過程。LangChain 可以輕松管理與語言模型的交互,將多個組件鏈接在一起,以便在不同的

    2024年02月16日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包