AI菜鸟向前飞 — LangChain系列之六 - 深入浅出LCEL与Chain(上篇)

615 阅读3分钟

简介

    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”)

按步骤解析每个可运行对象的处理的过程和内容:

image.png

首先, 让我们看一下代码的完整执行过程

程序

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逻辑是什么?(绘制了四张思维导图来说明)

Pasted image 20240424014436.png

Pasted image 20240424014514.png

Pasted image 20240424014538.png

Pasted image 20240424014602.png

还剩余“前后”两个,即:

  • 整体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...