当前位置:   article > 正文

langChain入门2-LCEL基本示例

lcel

LangChain Expression Language 既LCEL,是langchain核心中的核心,可以让我们方便的使用最基本的组件构建复杂的chains,并且支持一些开箱即用的功能包括流式输出、并行、以及日志输出
我们从两个最常用的langchain例子,来了解LCEL的使用。

基本示例1:prompt + model + output parser

这是最最基础且常见的langChain使用场景,将prompt template和一个llm连接到一起。
这里语言模型我们使用的是openAI chatgpt(如果你没法访问留言),同时你需要安装langchain的一些基本库。

pip install –upgrade –quiet langchain-core langchain-community langchain-openai
  • 1

我们让llm根据我们给出的topic讲一个笑话。

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

prompt = ChatPromptTemplate.from_template("tell me a short joke about {topic}")
model = ChatOpenAI()
output_parser = StrOutputParser()

# 这里就是LCEL
chain = prompt | model | output_parser

chain.invoke({"topic": "ice cream"})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

可以看到我们得到了一个笑话(虽然这并不可笑:)。

"Why don't ice creams ever get invited to parties?\n\nBecause they always drip when things heat up!"
  • 1

让我们注意这行代码,我们使用LCEL不同的组件拼到一起。

chain = prompt | model | output_parser
  • 1

这个|运算符非常类似unix的管道操作符,一个组件的输出作为另一个组件的输入。

在这个chain中,用户的输入传递给prompt template,组成了完整的template ,然后传递给模型,然后模型输出传递给输出解释器。

让我们看看每个组件实际发生了什么,以便更好的理解。

prompt

prompt是BasePromptTemplate的子类,在这个过程中输入了一个字典类型变量并产出一个PromptValue。

prompt_value = prompt.invoke({"topic": "ice cream"})  
prompt_value
  • 1
  • 2

PromptValue是一个包裹好的prompt,可以传递给语言模型。

ChatPromptValue(messages=[HumanMessage(content='tell me a short joke about ice cream')])
  • 1

prompt_value可以转为message形式(结构化)。

prompt_value.to_messages()
  • 1
[HumanMessage(content='tell me a short joke about ice cream')]
  • 1

也可以转为string

prompt_value.to_string()
  • 1
'Human: tell me a short joke about ice cream'
  • 1

Model

PromptValue 传递给model,在这个例子中model是一个ChatModel,输出一个BaseMessage。补充一个知识点,在langChain中,大语言模型分为LLM和ChatModel,LLM输入输出都是string,而ChatModel的输入输出都是BaseMessage的子类,分为AIMessage(模型输出)、HumanMessage(用户输入)、SystemMessage(系统输入)。

message = model.invoke(prompt_value)
message
  • 1
  • 2

model的输出是AIMessage类型。

AIMessage(content="Why don't ice creams ever get invited to parties?\n\nBecause they always bring a melt down!")
  • 1

Output parser

最后我们的模型输出结果传递给输出解释器,StrOutputParser会将Message转为String。

output_parser.invoke(message)
  • 1
"Why did the ice cream go to therapy? \n\nBecause it had too many toppings and couldn't find its cone-fidence!"
  • 1

回顾整个流程

Dict
PromptValue
ChatMessage
String
Input: topic=ice cream
PromptTemplate
ChatModel
StrOutputParser
Result

基本示例2:RAG search

首先我们解释一下什么是RAG,RAG(retrieval augmented generation ) 是检索增强式生成的意思,具体点来说就是通过检索一些相关信息,来组成prompt的上下文,llm会根据上下文内容生成,而不是根据自己学习过的知识生成,可以有效降低幻觉问题。

下面我们造一个demo,首先定义好一些知识,然后在输入大模型之前,我们先查询这些知识,根据这些知识,大模型再组织语言输出。

# Requires:
# pip install langchain docarray tiktoken

from langchain_community.vectorstores import DocArrayInMemorySearch
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_openai.chat_models import ChatOpenAI
from langchain_openai.embeddings import OpenAIEmbeddings

vectorstore = DocArrayInMemorySearch.from_texts(
    ["harrison worked at kensho", "bears like to eat honey"],
    embedding=OpenAIEmbeddings(),
)

retriever = vectorstore.as_retriever(search_kwargs={"k": 1})

template = """Answer the question based only on the following context:
{context}

Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
model = ChatOpenAI()
output_parser = StrOutputParser()

setup_and_retrieval = RunnableParallel(
    {"context": retriever, "question": RunnablePassthrough()}
)
chain = setup_and_retrieval | prompt | model | output_parser

chain.invoke("where did harrison work?")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

在这个示例中,编排的chain是:

chain = setup_and_retrieval | prompt | model | output_parser
  • 1

vectorStore

我首先看看vectorstore,这里使用了词向量技术,将两段内容使用OpenAIEmbeddings转为向量存储到了内存中。(如果不了解词向量,可以简单把它看成把一段文字的意思提取出来,存在一个多维数组中,在查询时,会把问题也矢量化,然后找到之前存入的与之比较匹配的数据,是一种相似性搜索技术。)

vectorstore = DocArrayInMemorySearch.from_texts(
    ["harrison worked at kensho", "bears like to eat honey"],
    embedding=OpenAIEmbeddings(),
)
  • 1
  • 2
  • 3
  • 4

retriever

retriever是对vectorstore的一种封装,支持LCEL,我们也可以像调用其他组件一样,直接调用retriever。注意这里search_kwargs={"k": 1}意思是只返回相似度最高的那条数据。

retriever = vectorstore.as_retriever(search_kwargs={"k": 1})
  • 1
retriever.invoke("where did harrison work?")

>>> [Document(page_content='harrison worked at kensho')]
  • 1
  • 2
  • 3

RunnableParallel

我们使用RunnableParallel对输入prompt template的数据进行预处理。RunnableParallel可以并行的处理其中的多个组件,最终将结果统一输出。将retriever的结果作为context,用户输入则原封不动作为question(使用RunnablePassthrough()保留原始输入)。最终组成一个dict传递给prompt template。

setup_and_retrieval = RunnableParallel(
    {"context": retriever, "question": RunnablePassthrough()}
)
  • 1
  • 2
  • 3

后续的步骤和上方的基本示例1相似,这里不再赘述。让我们回顾一下整个流程。

Question
Question
context=retreved docs
question=Quesstion
PromptValue
ChatMessage
str
Question
RunnableParallel
Retriever
RunnablePassThrough
PromptTemplate
ChatModel
StrOutputParser
Result
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/621607
推荐阅读
相关标签
  

闽ICP备14008679号