Langchian实战学习总结 | 豆包MarsCode AI 刷题

82 阅读20分钟

一、引言

Langchain 作为构建语言模型应用的强大工具,在人工智能领域正发挥着越来越重要的作用。本文将深入探讨 Langchain 的实战学习方法,为读者提供全面的指南。

Langchain 是一个开源框架,旨在帮助开发者构建以大型语言模型(LLM)为核心的应用程序。它通过提供一系列模块和工具,简化了语言模型与外部数据源、计算环境以及其他工具的集成过程,使得构建复杂的自然语言处理应用变得更加高效和便捷。

随着人工智能技术的不断发展,大型语言模型在自然语言处理中的应用变得越来越广泛。然而,如何有效地将这些强大的模型应用于实际场景,并与各种数据源和工具进行无缝集成,成为了开发者面临的重大挑战。Langchain 的出现正是为了解决这些问题。通过模块化和链式的设计理念,Langchain 提供了一个高度可扩展和灵活的框架,使得开发者可以专注于应用的核心功能,而无需过多关注底层实现。这不仅提高了开发效率,还为快速迭代和创新提供了有力支持。

二、Langchain 简介

Langchain 是什么以及发展过程

Langchain 是一个开源框架,旨在简化使用大型语言模型构建端到端应用程序的过程。

Langchain 于 2022 年 10 月开源,自开源以来发展迅速,获得了大量的关注和应用。在短短 11 个月里累计发布 200 多次,提交 4000 多次代码,目前已拥有 54K+ star。它最初可能只是创始人的一个业余爱好项目,但随着人工智能领域的发展,尤其是在 ChatGPT 发布一个月后,Langchain 在 GitHub 上获得了极大的关注,并迅速转变为一家初创公司,估值达到 2 亿美元。

Langchain 的发展历程可以追溯到对现有工具不足的反思,以及对如何更有效地使用大型语言模型构建应用程序的探索。它的出现为开发者提供了一个强大的工具,使得构建以大型语言模型为核心的应用程序变得更加高效和便捷。

三、Langchain 的功能与优势

功能一览

  1. 模型构造提示词,通过 I/O 系统管理输入输出。

Langchain 能够为模型构造合适的提示词,使得语言模型能够更好地理解任务需求并生成准确的输出。同时,它通过强大的 I/O 系统有效地管理输入和输出,确保数据的流畅传递和处理。

  1. 提供链式工具箱,支持检索增强生成式,以及代理和内存等功能。

Langchain 提供了丰富的链式工具箱,其中包括对检索增强生成式的支持。这意味着它可以结合外部数据源进行更准确和丰富的内容生成。此外,它还具备代理和内存功能,代理功能使得 Langchain 能够根据不同的输入自动决定最佳的处理方式,而内存功能则允许它记住先前的交互或数据,从而提供更连贯和上下文相关的响应。

优势

  1. 简化开发流程,降低开发门槛。

Langchain 通过提供一系列模块化的组件和工具,大大简化了开发流程。开发者无需从头开始构建所有的功能,而是可以直接使用 Langchain 提供的模块进行快速开发。这降低了开发门槛,使得即使没有深厚技术背景的开发者也能够轻松上手构建基于语言模型的应用程序。

  1. 模块化设计,灵活组合功能组件。

Langchain 的模块化设计使得各个功能组件可以独立开发、测试和维护。开发者可以根据具体的需求灵活地组合这些组件,构建出满足不同应用场景的解决方案。这种灵活性使得 Langchain 能够适应各种复杂的项目需求。

  1. 与外部系统集成,增强应用能力。

Langchain 能够与外部系统进行无缝集成,如数据库、APIs、文件系统等。这使得语言模型可以访问和利用外部数据源,从而增强了应用程序的能力和实用性。例如,可以将 Langchain 与数据库集成,实现基于数据库内容的问答系统。

  1. 提升效率与质量,提供社区支持。

Langchain 通过自动化测试用例生成、信息检索优化等特性,提高了开发和维护应用的效率。同时,它还保证了应用的性能和质量。此外,作为一个开源项目,Langchain 拥有活跃的开发者社区,不断贡献新的工具、插件和最佳实践,促进了技术的迭代和应用的创新。

四、Langchain 的劣势

学习曲线与依赖复杂性

  1. 有一定学习成本,对于新手有挑战。

Langchain 虽然旨在简化开发,但作为一套框架,它仍有一定的学习成本。尤其是对于初次接触大型语言模型和相关技术栈的开发者来说,可能会感到困惑。例如,Langchain 的结构可能令人费解,过多的抽象层次使得理解其实现的核心机制变得困难。过度依赖“辅助”函数,这些函数通常只是包装了标准的 Python 功能,也增加了学习的难度。

  1. 集成外部系统可能增加项目复杂性。

集成多个外部系统和工具可能会增加项目的复杂性。管理这些依赖关系和确保它们之间的兼容性可能成为一项挑战。例如,在使用 Langchain 时,可能需要同时处理多个外部数据源和工具,如数据库、向量数据库(如 Pinecone)、API 等。这不仅需要开发者具备丰富的技术知识,还需要花费大量的时间和精力来确保各个系统之间的正常交互。

性能与资源消耗

  1. 大型语言模型消耗较多计算资源。

大型语言模型本身在处理复杂任务时可能消耗较多计算资源,Langchain 虽然提供了优化手段,但在某些应用场景下,资源管理和成本控制仍需精细考虑。例如,在处理大规模数据集或进行复杂的推理任务时,可能会出现任务执行时间比预期的要长的情况。此外,ConversationRetrievalChain 倾向于重新表述用户输入,有时会打乱对话流程,这也可能影响性能。

安全性与模型定制化限制

  1. 需要注意数据安全和隐私保护。

与任何涉及敏感信息处理的技术一样,Langchain 的应用需要格外注意数据安全和隐私保护,确保符合法规要求并防止数据泄露。例如,通过使用微软的 LangChain 和 Presidio 库,可以为 LLM 应用程序创建一个安全且可定制的匿名化流水线。在初始化匿名器时,需要从 LangChain 初始化 PresidioReversibleAnonymizer,它提供了在匿名化后恢复原始数据的功能。然后,可以通过用占位符或标记替换已识别的 PII 实体来对文本进行匿名化处理。

  1. 对模型本身的微调或深度定制支持有限。

虽然 Langchain 支持与多种大型语言模型集成,但对于模型本身的微调或深度定制支持可能有限,开发者可能需要额外工作来适应特定领域的特殊需求。例如,在实际应用中,可能会发现 Langchain 在精确术语至关重要的专业行业中适应性有限。这是因为 Langchain 的抽象层次较高,可能无法满足特定领域对模型的精细调整需求。

五、Langchain 开发环境搭建

为什么用 Python

  1. 高级编程语言,易于学习和使用。

Python 作为一种高级编程语言,具有简洁易懂的语法,使得开发者能够快速上手。其代码结构清晰,可读性强,无论是对于初学者还是有经验的开发者来说,都能轻松理解和编写代码。

  1. 动态、直译式,可跳过编译执行代码。

Python 是一种动态类型的直译式语言,这意味着它可以在不进行编译的情况下直接执行代码。这种特性使得开发过程更加高效,开发者可以快速验证和调试代码,无需等待漫长的编译过程。同时,动态类型的特性也使得代码更加灵活,能够适应不同的开发需求。

  1. 广泛应用于多个领域,活跃社区和丰富库。

Python 在多个领域都有广泛的应用,包括 web 应用、软件、数据科学和机器学习等。在人工智能领域,Python 更是成为了主流语言之一。其活跃的社区为开发者提供了丰富的资源和支持,包括大量的开源库和工具。这些库涵盖了各种功能,如数据处理、机器学习算法、自然语言处理等,使得开发者能够快速构建复杂的应用程序。

环境要求

  1. Python 版本要求,推荐 3.10.12。

Langchain 需要 Python 3.8.1 以上版本,推荐使用 3.10.12。可以从 Python 官方网站(www.python.org/downloads/)下载并安装适合自己系统的版本。安装过程中,可以勾选“Add Python to PATH”选项,以便在命令提示符中直接运行 Python。

  1. 安装 Jupyter,参考安装使用教程。

Jupyter 是一个非常强大的交互式开发环境,特别适合数据科学和机器学习领域的开发。可以参考相关的安装使用教程,安装 Jupyter。安装完成后,可以通过在命令提示符中输入“jupyter notebook”来启动 Jupyter,进入一个在浏览器中运行的开发工具,地址为 localhost:8888

  1. 安装 Langchain,通过命令安装或使用开发工具插件。
  • 命令安装:可以使用 pip 或 conda 来安装 Langchain。例如,在命令提示符中输入“pip install langchain”或“conda install langchain -c conda-forge”。也可以指定具体的版本进行安装,如“pip install langchain==0.0.316 -i pypi.tuna.tsinghua.edu.cn/simple”。安装完成后,可以使用“pip show langchain”来查看安装的版本。
  • 使用开发工具插件:除了命令安装外,还可以使用 VS code/PyCharm 的 jupyter 插件启动 Langchain。这样可以在开发工具中直接使用 Langchain,提高开发效率。

安装 Langchain 后,还可以根据需要安装其他相关的库,如 openai 的 API 包。可以使用“pip install openai==0.28.1 -i pypi.tuna.tsinghua.edu.cn/simple”来安装 openai 的 API 包。或者使用 Baichuan、ChatGLM 这样的开源包。

安装 Langchain 的过程中,可能需要注意以下几点:

  • 版本兼容性:不同版本的 Langchain 可能与其他库存在兼容性问题。在安装时,需要注意选择合适的版本,以确保各个库之间能够正常工作。
  • 依赖管理:安装 Langchain 可能会依赖其他库,需要确保这些依赖库也被正确安装。可以使用虚拟环境来管理依赖,避免不同项目之间的依赖冲突。
  • 安装源:为了提高安装速度,可以选择使用国内的安装源,如清华源。在安装命令中添加“-i pypi.tuna.tsinghua.edu.cn/simple”即可使用清华源进行安装。

六、Langchain 实战案例

用 Langchain 写 Python 代码并执行

  1. 完整代码示例,实现功能介绍。

以下是一个使用 Langchain 让大模型写 Python 代码并自动执行输出结果的示例代码:

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import (ChatPromptTemplate,)
from langchain_experimental.utilities import PythonREPL
from langchain_openai import ChatOpenAI
template = """Write some python code to solve the user's problem.
Return only python code in Markdown format, e.g.:```python....```"""
prompt = ChatPromptTemplate.from_messages([("system", template), ("human", "{input}")])
model = ChatOpenAI()
def _sanitize_output(text: str):
    _, after = text.split("```python")
    return after.split("```")[0]
chain = prompt | model | StrOutputParser() | _sanitize_output | PythonREPL().run
result = chain.invoke({"input": "whats 2 plus 2"})
print(result)

这段代码实现的功能是:当接收到用户提问时,通过调用大模型来写 Python 代码,通过执行 Python 代码输出 Python 代码的运行结果。例如,用户提问“2+2等于几”,Python 程序执行结果为 4。

  1. 代码学习,分析传统 chain 部分、输出处理函数和执行类的作用。

(1)首先是前面的传统 chain 部分,prompt | model | StrOutputParser就是将用户提问和系统设定的 Prompt 给到大模型,然后大模型输出结果,通过StrOutputParser将结果转换成字符串格式。StrOutputParser的作用是将大模型的输出转换成字符串格式。如果是 LLM 的返回,保持原样(LLM 的返回本来就是字符串),如果是 ChatModel 的返回,它会输出.content中的信息作为结果字符串。这里面可以重点关注下给系统设定的 Prompt:限定了只输出 Python 代码,并且用 Markdown 的形式,并且还给了输出格式的例子,最大限度地保证大模型输出的 Python 代码是可以运行的。

template = """Write some python code to solve the user's problem.
Return only python code in Markdown format, e.g.:```python....```"""

(2)_sanitize_output函数,将大模型输出的 Markdown 格式的 Python 代码提取出来,其实这里就是去掉前面的“python”和后面的“”。所以,前面的 Prompt 就显得至关重要了,一定将输出格式限制死了,有一点不对就会提取 Python 代码出错。

(3)PythonREPL().run,从代码中也能猜出它就是用来在内部运行 Python 程序的,它是 LangChain 封装的一个用来执行 Python 代码的类。run函数的几个注意点:参数为完整的要执行的 Python 代码;其返回结果为 Python 代码中通过print函数打印的内容,如下示例代码,print(1+1),才能返回 2。

from langchain_experimental.utilities import PythonREPL
python_repl = PythonREPL()
python_repl.run("print(1+1)") # 有返回值,2
python_repl.run("print(1+1)") # 无返回值,空的

查看PythonREPL的源码,原理很简单,就是调用了一下exec函数执行代码,然后将标准输出中的内容放到队列中。执行完之后return queue.get(),将标准输出内容作为结果返回。所以从源码也可以知道,它不止会返回print打印出来的内容,任何输出到标准输出中的信息它都会返回,例如程序报错、警告等。

起名大师案例

  1. 自定义提示词模版,输出解释器格式化结果。

将提问的上下文模版化支持参数传入,让 LLM 给孩子起具有特定特色的名字。将提示词模版化后会产生很多灵活多变的应用,尤其当它支持参数定义时。使用方法是langchain.prompts。例如:

from langchain.prompts import PromptTemplate
from llmself.makeLLm import Kimi
# 提示此模版内容
template = """ 请将由三个反引号分隔的文本内容用"{language}"进行翻译```{text}```"""
# 创建提示词模版
prompt_template = PromptTemplate(input_variables=["text", "language"], template=template)
text = f"""您应该提供尽可能清晰和具体的指令来表达您希望模型执行的任务。
这将引导模型朝着期望的输出方向发展,并减少接收到不相关或不正确响应的可能性。
不要将编写清晰提示与编写简短提示混淆。在许多情况下,
更长的提示提供更多的清晰度和上下文,这可能会导致更详细和相关的输出。"""
llm = Kimi()
# 测试提示词模版
print(llm.invoke(prompt_template.format(text=text, language="英文")))
  1. 完整案例展示,以数组形式输出具有特定特色的名字。

以下是一个起名大师的完整案例,使用 Langchain 输出具有特定特色的名字,并以数组形式返回:

from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
import os
from langchain.schema import BaseOutputParser
# 自定义类
class CommaSeparatedListOutputParser(BaseOutputParser):
    """Parse the output of an LLM call to a comma-separated list."""
    def parse(self, text: str):
        """Parse the output of an LLM call."""
        print(text)
        return text.strip().split(",")
api_base = os.getenv("OPENAI_API_BASE")
api_key = os.getenv("OPENAI_KEY")
llm = OpenAI(model="gpt-3.5-turbo-instruct", temperature=0, openai_api_key=api_key, openai_api_base=api_base)
prompt = PromptTemplate.from_template("你是一个起名大师,请模仿示例起 3 个具有{county}特色的名字,示例:男孩常用名{boy},女孩常用名{girl}。请返回以逗号分隔的列表形式。仅返回逗号分隔的列表,不要返回其他内容。")
message = prompt.format(county="美国男孩", boy="sam", girl="lucy")
print(message)
strs = llm.predict(message)
CommaSeparatedListOutputParser().parse(strs)

七、Langchain 实战心得与经验分享

大模型开发问题与 Langchain 学习背景

  1. 微场景跳转、幻读、知识库检索等问题。

在大模型开发过程中,常常会遇到一些问题。例如微场景间跳转问题,无法实现微场景随意穿插;大模型幻读,可能会推荐不存在的产品或自己发挥;知识库检索方面,语义匹配效果较差,匹配出的结果和客户表述的语义有差异;此外,还有场景外话题防护问题,如作诗、编码、翻译、敏感信息、政治任务讨论等需要进行防护,多场景切换也不支持。这些问题给大模型开发带来了挑战。

  1. Langchain 框架学习的必要性。

面对大模型开发中的种种问题,学习 Langchain 框架变得十分必要。Langchain 通过提供模块化组件简化了开发流程,具有上下文感知能力,能将语言模型连接到上下文来源,同时依赖语言模型进行推理,根据提供的上下文决定如何回答和采取什么行动。

Agent 设计模式

  1. 反思模式、使用工具、规划、多智能体协作等模式介绍。
  • 反思模式:让 Agent 审视和修正自己生成的输出。例如在吴恩达教授提出的 AI 智能体工作流中,反思指的是智能体在完成任务后,能够自我审视其产出,并主动寻找潜在的改进空间。
  • 使用工具:LLM 生成代码、调用 API 等进行实际操作。如在 LangChain 中,智能体可以利用网络搜索、代码执行等工具来收集信息、采取行动或处理数据。
  • 规划:让 Agent 分解复杂任务并按计划执行。智能体可以制定并执行多步骤计划来达成目标。
  • 多智能体协作:多个 Agent 扮演不同角色合作完成任务。多个智能体共同工作,通过分配任务和讨论来提出更优的解决方案。

Langchain 版本迭代与核心组件

  1. 版本更新历程,核心组件包括 Models、Prompts、Memory、Chains、Agents、Rag 等。

Langchain 自 2022 年 10 月开源以来,不断进行版本迭代。稳定版本 0.1.0 于 2024 年 1 月 8 日发布,最新稳定版本 0.1.17 于 2024 年 5 月 1 日发布。Langchain 的核心组件丰富多样,包括与语言模型进行交互的 Models,其中有输入文本字符串并返回文本字符串的模型(LLMs)和接受聊天消息列表作为输入并返回聊天消息的聊天模型;Prompts 用于提示词工程;Memory 提供内存记忆功能,在对话过程中存储数据以提供上下文;Chains 构建调用链,把一个个独立的组件链接在一起;Agents 作为代理,执行复杂任务;Rag 检索增强包括文本嵌入模型、向量存储、文档加载器和转换器、检索(向量+关键字)等。

使用框架的优缺点

  1. 优点如简化开发、提高可拓展性等。
  • 简化开发流程,提高开发效率:Langchain 提供了一系列模块化的组件和工具,大大简化了开发流程。开发者无需从头开始构建所有的功能,而是可以直接使用 Langchain 提供的模块进行快速开发。
  • 提高项目可拓展性:Langchain 的模块化设计使得各个功能组件可以独立开发、测试和维护。开发者可以根据具体的需求灵活地组合这些组件,构建出满足不同应用场景的解决方案。
  • 能够实现多代理工作流编排:Langchain 支持多代理协作,多个 Agent 可以扮演不同角色合作完成任务,实现复杂的工作流编排。
  • 可观测性和调试:通过与 LangSmith 的紧密集成,LangChain 在可观察性方面做到了业界领先。可以记录每个步骤的输入输出、所需时间等调试信息,支持不同粒度的日志记录,实现可视化 chain 的方法,提供获取所有使用提示的方法。
  1. 缺点包括框架未成熟、学习成本和业务设计要求高。
  • 框架还未成熟,模型支持力度不同:Langchain 作为一个新兴的框架,仍在不断发展和完善中。不同的模型在 Langchain 中的支持力度可能存在差异,这给开发者带来了一定的挑战。
  • 学习成本:虽然 Langchain 旨在简化开发,但作为一套框架,它仍有一定的学习成本。尤其是对于初次接触大型语言模型和相关技术栈的开发者来说,可能会感到困惑。例如,Langchain 的结构可能令人费解,过多的抽象层次使得理解其实现的核心机制变得困难。
  • 框架封装后,隐藏了很多细节,业务设计要求高:Langchain 的封装性使得一些细节被隐藏起来,这对业务设计提出了更高的要求。开发者需要在理解框架的基础上,进行合理的业务设计,以充分发挥 Langchain 的优势。

八、Langchain 实战学习方法总结

  1. 从理论到实践,逐步掌握 Langchain 的应用。
    • 学习 Langchain 可以从了解其基本概念和功能入手,逐步深入到实际应用中。首先,要熟悉 Langchain 的架构和各个组件的作用,包括模型输入/输出、检索、链、记忆和代理等。然后,可以通过实际的项目案例来加深对 Langchain 的理解和掌握。
    • 在实践过程中,要注重代码的实现和调试。可以参考官方文档和示例代码,逐步构建自己的应用程序。同时,要注意学习曲线和依赖复杂性,对于新手来说,可能需要花费一定的时间和精力来掌握 Langchain 的使用方法。
  1. 参考资料和学习资源推荐,帮助读者深入学习。
    • 在线博客和文章是学习 Langchain 的重要资源之一。例如,CSDN 博客上的“【LangChain编程:从入门到实践】资源和工具推荐”和“使用LangChain的自定义示例选择器:从理论到实践”等文章,提供了丰富的 Langchain 学习资源和实际案例。
    • 书籍也是学习 Langchain 的好选择。如“放弃LangChain?建议读完这本书再下定论_51CTO博客-放弃好吗?”中推荐的《LangChain实战:大模型应用开发实例》,基于 LangChain 首个稳定版本编写,内容涵盖了 LangChain 的核心概念、应用和实战经验,适合初学者和专业开发者。
    • 此外,Langchain 的官方文档、社区论坛和开源项目也是学习的重要资源。可以通过阅读官方文档了解 Langchain 的最新功能和使用方法,参与社区论坛讨论解决问题,研究开源项目学习他人的经验和技巧。