简介
LCEL是 LangChain Expression Language的缩写
先来做个程序书写的对比,观察一下、使用了Expression Language语法之后更加短小精悍(缩短了一倍长度,更加高级的用法缩短会更多)而且代码看起来更加简单易读。
- 使用EL
from langchain_community.chat_models import ChatOllama
from langchain.schema import HumanMessage
from langchain_core.output_parsers import StrOutputParser
(ChatOllama(model="llama3", temperature=0) | StrOutputParser()).invoke([HumanMessage(content="你好啊, AI小助手")])
- 未使用EL
from langchain_community.chat_models import ChatOllama
from langchain.schema import HumanMessage
from langchain_core.output_parsers import StrOutputParser
chat = ChatOllama(model="llama3", temperature=0)
output_parser = StrOutputParser()
response = chat.invoke([HumanMessage(content="你好啊, AI小助手")])
output_parser.invoke(response)
Expression Language是一种将 Runnable 组成链 (Runnables into chains) 的声明性方式,以这种方式构建的任何链都将自动具有同步、异步、批处理、流支持等等,包含RunnableSequence 和 RunnableParallel两大部分内容。
关于RunnableParallel内容,放到后面再介绍
RunnableSequence:按顺序调用一系列可运行对象,一个可运行对象的输出充当下一个可运行对象的输入,使用管道符号(即“|”)来分割两个对象。
chain = prompt | model | output_parser
chain.invoke({"text": "你好啊, AI小助手"})
用一张图简单描绘这流式传输吧:
把上图的组成统一成一个Chain(就是LangChain的“Chain”)
按步骤解析每个可运行对象的处理的过程和内容:
首先, 让我们看一下代码的完整执行过程
程序
from langchain_community.chat_models import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_template("{text}")
model = ChatOllama(model="llama3", temperature=0)
output_parser = StrOutputParser()
chain = prompt | model | output_parser
response = chain.invoke({"text": "你好啊, AI小助手"})
print(response)
输出结果
[chain/start] [1:chain:RunnableSequence] Entering Chain run with input:
{
"text": "你好啊, AI小助手"
}
[chain/start] [1:chain:RunnableSequence > 2:prompt:ChatPromptTemplate] Entering Prompt run with input:
{
"text": "你好啊, AI小助手"
}
[chain/end] [1:chain:RunnableSequence > 2:prompt:ChatPromptTemplate] [0ms] Exiting Prompt run with output:
[outputs]
[llm/start] [1:chain:RunnableSequence > 3:llm:ChatOllama] Entering LLM run with input:
{
"prompts": [
"Human: 你好啊, AI小助手"
]
}
[llm/end] [1:chain:RunnableSequence > 3:llm:ChatOllama] [5.28s] Exiting LLM run with output:
{
"generations": [
[
{
"text": "😊 你好啊!我是你的AI小助手,欢迎你来到这里!有什么问题或需求,请随时问我,我会尽力帮助你。😊",
"generation_info": {
"model": "llama3",
"created_at": "2024-04-23T17:37:18.840986487Z",
"message": {
"role": "assistant",
"content": ""
},
"done": true,
"total_duration": 5271991298,
"load_duration": 1043179188,
"prompt_eval_count": 18,
"prompt_eval_duration": 1174320000,
"eval_count": 40,
"eval_duration": 2919644000
},
"type": "ChatGeneration",
"message": {
"lc": 1,
"type": "constructor",
"id": [
"langchain",
"schema",
"messages",
"AIMessage"
],
"kwargs": {
"content": "😊 你好啊!我是你的AI小助手,欢迎你来到这里!有什么问题或需求,请随时问我,我会尽力帮助你。😊",
"tool_calls": [],
"invalid_tool_calls": []
}
}
}
]
],
"llm_output": null,
"run": null
}
[chain/start] [1:chain:RunnableSequence > 4:parser:StrOutputParser] Entering Parser run with input:
[inputs]
[chain/end] [1:chain:RunnableSequence > 4:parser:StrOutputParser] [0ms] Exiting Parser run with output:
{
"output": "😊 你好啊!我是你的AI小助手,欢迎你来到这里!有什么问题或需求,请随时问我,我会尽力帮助你。😊"
}
[chain/end] [1:chain:RunnableSequence] [5.28s] Exiting Chain run with output:
{
"output": "😊 你好啊!我是你的AI小助手,欢迎你来到这里!有什么问题或需求,请随时问我,我会尽力帮助你。😊"
}
😊 你好啊!我是你的AI小助手,欢迎你来到这里!有什么问题或需求,请随时问我,我会尽力帮助你。😊
上一个的输出就是下一个的输入
再分析, 整个Pipeline中每一个可运行的对象,其底层的jsonschema逻辑是什么?(绘制了四张思维导图来说明)
还剩余“前后”两个,即:
- 整体Pipeline Chain输入的Schema(即:prompt的输入的json schema)
{"title": "PromptInput",
"type": "object",
"properties": {
"text":
{"title": "Text", "type": "string"}
}
}
- 整体Pipeline Chain输出的Schema(即:output_parser的输出的json schema)
{"title": "StrOutputParserOutput", "type": "string"}
To be continue...