码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 22. LangChain LCEL,用 | 串联AI的魔法语言


    合集 - AI应用开发实战(32)
    1.1. AI应用实战开发04-292.2.【保姆级入门】什么是 AI?人工智能到底能干嘛?看完秒懂!04-293.3. AI大模型架构图和盈利模式04-304.4. Token(词元),5分钟彻底搞懂04-305.5. AI大模型的不足和解决方案04-306.6. LangChain,解决AI大模型的不足05-017.7. 搞懂LangChain开发库,还有dotenv实战05-028.8.【保姆级】从零学会LangChain调用大模型!统一接口+代码实战05-039.9. LangChain 6大核心参数详解 + 代码实战,看完就能直接用05-0410.10. LangChain开发核心技巧,动态切换AI大模型参数05-0511.11. LangChain实用技巧,轻松切换AI大模型05-0612.12. LangChain 6大核心调用方法:invoke/stream/batch同步异步全解析,新手也能轻松学会05-0713.13. 学会提示词,从此 AI 听你指挥05-0814.14. 别再硬写提示词了!LangChain PromptTemplate从入门到实战05-1215.15. 别再硬写提示词了!LangChain ChatPromptTemplate核心实战05-1516.16. LangChain ChatPromptTemplate多模态应用实战05-1617.17. LangChain FewShotPromptTemplate少样本应用实战05-1718.18. LangChain输出解析器实战:从大模型输出到结构化数据的转化05-1819.19. 大模型输出乱成渣?3个解析器轻松转成标准列表!05-1920.20. AI大模型输出转JSON,原来这么简单!05-2021.21. “|”不只是按位或,90%的人不知道05-21
    22.22. LangChain LCEL,用 | 串联AI的魔法语言05-24
    23.23. AI 智能体真的很难吗?5分钟一次性讲明白06-0124.24. LangChain内置工具,开发效率提升10倍!06-0325.25. AI 总是 “失忆“?3 行代码让它记住你!06-0626.26. Agent 记不住业务数据?用 Store 给它加个“笔记本“!06-1327.27. Agent 需要拦截模型调用?用 Middleware 给它加个“拦截器“!06-1428.28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!06-1829.29. MCP协议,让大模型自己调用工具06-2230.30. AI Skills技能系统,让 Agent 自动变强06-2431.31. RAG 检索增强生成,让大模型拥有外部知识07-0632.32. 从 LangChain 到实战落地:一条清晰的智能体技术进阶路径(完结篇)07-07
    收起

    在 LangChain 生态中,LCEL(LangChain Expression Language)是一种新的编程范式。它用一个简单的|,改变了 AI 应用的构建方式。曾经需要编写大量胶水代码才能串联起来的提示词、模型和输出解析器,现在只需要一行代码就能完成:

    chain = prompt | model | parser

    1. LCEL 核心原理:| 运算符的秘密
    LCEL 的核心设计哲学就是 "数据流优先"。所有组件都遵循统一的接口,数据从左向右沿着链条自动流动,无需开发者手动处理中间状态。

    链式组合:LCEL 使用|(竖线)运算符串联 Prompt、模型与输出解析器形成 AI 流水线,数据严格按照从左到右的顺序传递。

    底层实现:| 运算符本质上是 Python 中__or__方法的语法糖。

    Runnable 基类:LangChain 中所有可执行组件都继承自Runnable基类,该基类重载了__or__方法,这就是为什么所有组件都能使用|进行链式组合的根本原因。

    image

     2. 三步构建你的第一条 AI 链

    下面,让我们从最简单的例子开始,用 LCEL 构建一个笑话生成器。这个例子将展示 LCEL 最核心的用法:串联提示词、模型和字符串输出解析器。

    复制代码
    import os
    from dotenv import load_dotenv
    from langchain.chat_models import init_chat_model
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
     
    # 加载环境变量(包含API密钥、模型名称等)
    load_dotenv()
     
    # 初始化模型(使用config_prefix支持多模型配置)
    prefix = "QWEN"
    model = init_chat_model(
        model_provider="openai",
        configurable_fields=["model", "api_key", "base_url"],
        config_prefix=prefix,
        temperature=0.5,
        max_tokens=500
    )
     
    # 模型配置(从环境变量中读取)
    config = {
        "configurable": {
            f"{prefix}_model": os.getenv(f"{prefix}_MODEL"),
            f"{prefix}_api_key": os.getenv(f"{prefix}_API_KEY"),
            f"{prefix}_base_url": os.getenv(f"{prefix}_BASE_URL")
        }
    }
     
    # 创建提示词模板
    prompt = ChatPromptTemplate.from_messages(
        [
            {"role": "system", "content": "你是一个笑话大王"},
            {"role": "user", "content": "{new_input}"}
        ]
    )
     
    # 用LCEL构建完整链条
    chain = prompt | model | StrOutputParser()
     
    # 执行链条,传入原始输入
    result = chain.invoke({"new_input": "讲一个笑话"}, config=config)
    print(result)
    复制代码

    3. 进阶用法:什么可以入链?
    LCEL 的强大之处在于它的包容性。几乎任何逻辑都可以被包装成 Runnable 组件,然后无缝接入流水线。但有一个核心规则必须牢记:

    入链的内容必须是 Runnable 的子类,字典的值也必须符合这个规则。

    下面是不同数据类型的处理方式对照表:

    数据类型 处理方式 对应 Runnable子类 核心作用
    静态值 包装为lambda _: 静态值 RunnableLambda 生成固定值
    函数/lambda表达式 直接使用(自动转换) RunnableLambda 执行自定义逻辑
    动态值 使用RunnablePassthrough() RunnablePassthrough 原样传递数据
    字典 直接使用,值也要符合规范 RunnableParallel 并行执行多分支
    让我们用一个例子来演示这些规则。我们将构建一个能生成结构化 JSON 数据的 AI 链,这在实际应用中非常常见。

    RunnablePassthrough():当你直接传入字符串"请描述一下张三..."时,RunnablePassthrough()会将这个字符串原样传递给new_input变量。

    lambda _: parser.get_format_instructions():这里的下划线_表示我们不关心上游输入,因为格式指令是固定的。这个 lambda 会被自动转换为RunnableLambda。

    字典入链:整个字典会被转换为RunnableParallel对象,它会并行执行所有键对应的 Runnable,然后将结果合并为一个新的字典传递给下一个组件(这里是 prompt)。

    复制代码
    import os
    from dotenv import load_dotenv
    from langchain.chat_models import init_chat_model
    import asyncio
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import JsonOutputParser
    from langchain_core.runnables import RunnablePassthrough
     
    load_dotenv()
    prefix = "QWEN"
    model = init_chat_model(
        model_provider="openai",
        configurable_fields=["model", "api_key", "base_url"],
        config_prefix=prefix,
        temperature=0.5,
        max_tokens=500
    )
    config = {
        "configurable": {
            f"{prefix}_model": os.getenv(f"{prefix}_MODEL"),
            f"{prefix}_api_key": os.getenv(f"{prefix}_API_KEY"),
            f"{prefix}_base_url": os.getenv(f"{prefix}_BASE_URL")
        }
    }
     
    prompt = ChatPromptTemplate.from_messages(
        [
            {"role": "system", "content": "你是一位有10年经验的资深软件工程师。{format_instructions}"},
            {"role": "user", "content": "{new_input}"}
        ]
    )
     
    parser = JsonOutputParser()
    chain = (
            {
                "new_input": RunnablePassthrough(),
                "format_instructions": lambda _: parser.get_format_instructions()
            }
            | prompt
            | model
            | parser
    )
    result = chain.invoke("请描述一下张三这个人,包括姓名、年龄、职业和兴趣爱好。", config=config)
    print(result)
    复制代码

    4. 函数入链:无缝集成自定义逻辑

    LCEL 最强大的特性之一就是可以轻松将任意 Python 函数接入流水线。函数会被自动转换为RunnableLambda,无需任何额外的包装代码。

    让我们扩展上一个例子,添加一个函数将生成的 JSON 数据自动保存到本地文件。

    复制代码
    import json
    import os
    from dotenv import load_dotenv
    from langchain.chat_models import init_chat_model
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import JsonOutputParser
    from langchain_core.runnables import RunnablePassthrough
     
    load_dotenv()
     
    prefix = "QWEN"
    model = init_chat_model(
        model_provider="openai",
        configurable_fields=["model", "api_key", "base_url"],
        config_prefix=prefix
    )
     
    config = {
        "configurable": {
            f"{prefix}_model": os.getenv(f"{prefix}_MODEL"),
            f"{prefix}_api_key": os.getenv(f"{prefix}_API_KEY"),
            f"{prefix}_base_url": os.getenv(f"{prefix}_BASE_URL")
        }
    }
     
    # 自定义函数:保存JSON数据到文件
    def save_json(data, filename="output.json"):
        try:
            with open(filename, "w", encoding="utf-8") as f:
                json.dump(data, f, ensure_ascii=False, indent=4)
            print(f"JSON数据已成功保存到 {filename}")
        except Exception as e:
            print(f"保存JSON文件时出错: {e}")
        return data  # 重要:返回数据以便继续传递给下一个组件
     
    parser = JsonOutputParser()
    prompt = ChatPromptTemplate.from_messages(
        [
            {"role": "system", "content": "你是一位有10年经验的资深软件工程师。{format_instructions}"},
            {"role": "user", "content": "{new_input}"}
        ]
    )
     
    # 将自定义函数直接加入链条
    chain = ({
                 "new_input": RunnablePassthrough(),
                 "format_instructions": lambda _: parser.get_format_instructions()
             }
             | prompt
             | model
             | parser
             | save_json  # 函数直接入链
             )
     
    result = chain.invoke("请描述一下张三这个人,包括姓名、年龄、职业和兴趣爱好。", config=config)
    print(result)
    复制代码

    运行这段代码后,你会在当前目录下看到一个output.json文件,内容如下:

    复制代码
    {
        "姓名": "张三",
        "年龄": 30,
        "职业": "软件工程师",
        "兴趣爱好": [
            "阅读技术书籍",
            "徒步旅行",
            "围棋"
        ]
    }
    复制代码

    重要提示:自定义函数必须返回数据,这样数据才能继续传递给链条中的下一个组件。如果函数没有返回值(返回None),那么链条的后续组件将收到None作为输入。

     

  • 相关阅读:
    2023版IDEA的下载、安装、配置、快捷键、模板、插件与使用
    【构建ML驱动的应用程序】第 5 章 :训练和评估模型
    爬某网站延禧宫率第一集视频
    [附源码]计算机毕业设计JAVA人力资源管理系统论文2022
    k8s-statefulset创建mongo集群
    S7COMM协议分析
    【Chips】如何用DPI调用C++程序,并成功仿真
    Windows 环境搭建 PostgreSQL 物理复制高可用架构数据库服务
    【计算机组成原理】第三章 存储系统
    三篇论文入选国际顶会SIGMOD,厉害了腾讯云数据库
  • 原文地址:https://www.cnblogs.com/halfcode/p/20143984
  • 最新文章
  • 沪漂五周年了:我越来越迷茫了
    Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
    MySQL-Seconds_behind_master的精度误差
    [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
    AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
    Agent OS :五种驯服不确定性的范式
    PortSwigger SQL注入LAB11
    数据库即时编译JIT
    [Begin]AI Learn Data Day 0
    深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号