My Little World

LangChain

LangChain 也是一套面向大模型的开发框架(SDK)

  1. LangChain 是 AGI 时代软件工程的一个探索和原型
  2. 学习 LangChain 要关注接口变更

LangChain 的核心组件

  1. 模型 I/O 封装
    • LLMs:大语言模型
    • Chat Models:一般基于 LLMs,但按对话结构重新封装
    • PromptTemple:提示词模板
    • OutputParser:解析输出
  2. 数据连接封装
    • Document Loaders:各种格式文件的加载器
    • Document Transformers:对文档的常用操作,如:split, filter, translate, extract metadata, etc
    • Text Embedding Models:文本向量化表示,用于检索等操作
    • Verctorstores: (面向检索的)向量的存储
    • Retrievers: 向量的检索
  3. 记忆封装
    • Memory:这里不是物理内存,从文本的角度,可以理解为”上文”、”历史记录”或者说”记忆力”的管理
  4. 架构封装
    • Chain:实现一个功能或者一系列顺序功能组合
    • Agent:根据用户输入,自动规划执行步骤,自动选择每步需要的工具,最终完成用户指定的功能
      • Tools:调用外部功能的函数,例如:调 google 搜索、文件 I/O、Linux Shell 等等
      • Toolkits:操作某软件的一组工具集,例如:操作 DB、操作 Gmail 等等
  5. Callbacks

模型 I/O 封装

通过模型封装,实现不同模型的统一接口调用

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
33
34
35
36
37
38
39
40
41
from langchain_openai import ChatOpenAI
from langchain.schema import (
AIMessage, # 等价于OpenAI接口中的assistant role
HumanMessage, # 等价于OpenAI接口中的user role
SystemMessage # 等价于OpenAI接口中的system role
)
from langchain_community.chat_models import QianfanChatEndpoint
from langchain_core.messages import HumanMessage

# OpenAI 模型封装
llm = ChatOpenAI(model="gpt-3.5-turbo") # gpt-4o 默认是gpt-3.5-turbo
response = llm.invoke("你是谁")
print(response.content)

# 多轮对话 Session 封装
messages = [
SystemMessage(content="你是AGIClass的课程助理。"),
HumanMessage(content="我是学员,我叫王卓然。"),
AIMessage(content="欢迎!"),
HumanMessage(content="我是谁")
]

ret = llm.invoke(messages)

print(ret.content)

# 国产模型 其它模型分装在 langchain_community 底包中
import os

llm = QianfanChatEndpoint(
qianfan_ak=os.getenv('ERNIE_CLIENT_ID'),
qianfan_sk=os.getenv('ERNIE_CLIENT_SECRET')
)

messages = [
HumanMessage(content="你是谁")
]

ret = llm.invoke(messages)

print(ret.content)

Prompt 模板封装

1
2
3
4
5
6
7
from langchain.prompts import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
SystemMessagePromptTemplate,
MessagesPlaceholder,
PromptTemplate
)
  1. PromptTemplate 可以在模板中自定义变量
  2. ChatPromptTemplate 用模板表示的对话上下文
  3. MessagesPlaceholder 把多轮对话变成模板
  4. 从文件加载 Prompt 模板: PromptTemplate.from_file

把Prompt模板看作带有参数的函数

输出封装 OutputParser

自动把 LLM 输出的字符串按指定格式加载。
LangChain 内置的 OutputParser 包括:

  1. ListParser
  2. DatetimeParser
  3. EnumParser
  4. JsonOutputParser
  5. PydanticParser
  6. XMLParser

等等

Pydantic (JSON) Parser

自动根据 Pydantic 类的定义,生成输出的格式说明

Auto-Fixing Parser

利用 LLM 自动根据解析异常修复并重新解析

小结

  1. LangChain 统一封装了各种模型的调用接口,包括补全型和对话型两种
  2. LangChain 提供了 PromptTemplate 类,可以自定义带变量的模板
  3. LangChain 提供了一些列输出解析器,用于将大模型的输出解析成结构化对象;额外带有自动修复功能。
  4. 上述模型属于 LangChain 中较为优秀的部分;美中不足的是 OutputParser 自身的 Prompt 维护在代码中,耦合度较高。

数据连接封装

1
2
3
4
5
6
7
8
9
10
# 文档加载器:Document Loaders
from langchain_community.document_loaders import PyMuPDFLoader
# 文档处理器 TextSplitter
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 向量数据库与向量检索
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_openai import ChatOpenAI
from langchain_community.document_loaders import PyMuPDFLoader

类似 LlamaIndex,LangChain 也提供了丰富的 Document LoadersText Splitters

小结

  1. 文档处理部分,建议在实际应用中详细测试后使用
  2. 与向量数据库的链接部分本质是接口封装,向量数据库需要自己选型

记忆封装:Memory

1
2
3
4
5
6
7
8
# 对话上下文:ConversationBufferMemory
from langchain.memory import ConversationBufferMemory, ConversationBufferWindowMemory

# 只保留一个窗口的上下文:ConversationBufferWindowMemory
from langchain.memory import ConversationBufferWindowMemory

# 通过 Token 数控制上下文长度:ConversationTokenBufferMemory
from langchain.memory import ConversationTokenBufferMemory

更多类型

  1. ConversationSummaryMemory: 对上下文做摘要
  2. ConversationSummaryBufferMemory: 保存 Token 数限制内的上下文,对更早的做摘要
  3. VectorStoreRetrieverMemory: 将 Memory 存储在向量数据库中,根据用户输入检索回最相关的部分

小结

  1. LangChain 的 Memory 管理机制属于可用的部分,尤其是简单情况如按轮数或按 Token 数管理;
  2. 对于复杂情况,它不一定是最优的实现,例如检索向量库方式,建议根据实际情况和效果评估;
  3. 但是它对内存的各种维护方法的思路在实际生产中可以借鉴

LangChain Expression Language(LCEL)是一种声明式语言,可轻松组合不同的调用顺序构成 Chain。LCEL 自创立之初就被设计为能够支持将原型投入生产环境,无需代码更改,从最简单的”提示+LLM”链到最复杂的链(已有用户成功在生产环境中运行包含数百个步骤的 LCEL Chain)。

LCEL 的一些亮点包括:

  1. 流支持
  2. 异步支持
  3. 优化的并行执行
  4. 重试和回退
  5. 访问中间结果
  6. 输入和输出模式
  7. 无缝 LangSmith 跟踪集成
  8. 无缝 LangServe 部署集成

原文:https://python.langchain.com/docs/expression_language/

Pipeline 式调用 PromptTemplate, LLM 和 OutputParser

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser, PydanticOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_core.pydantic_v1 import BaseModel, Field, validator
from typing import List, Dict, Optional
from enum import Enum
import json

# LCEL 表达式
runnable = (
{"text": RunnablePassthrough()} | prompt | model | parser
)

# 直接运行
ret = runnable.invoke("不超过100元的流量大的套餐有哪些")

# 流式输出
for s in runnable.stream("不超过100元的流量大的套餐有哪些"):
print(s, end="")

使用 LCEL 的价值,也就是 LangChain 的核心价值。

官方从不同角度给出了举例说明:https://python.langchain.com/docs/expression_language/why

通过 LCEL,还可以实现

  1. 配置运行时变量:https://python.langchain.com/docs/expression_language/how_to/configure
  2. 故障回退:https://python.langchain.com/docs/expression_language/how_to/fallbacks
  3. 并行调用:https://python.langchain.com/docs/expression_language/how_to/map
  4. 逻辑分支:https://python.langchain.com/docs/expression_language/how_to/routing
  5. 调用自定义流式函数:https://python.langchain.com/docs/expression_language/how_to/generators
  6. 链接外部 Memory:https://python.langchain.com/docs/expression_language/how_to/message_history

更多例子:https://python.langchain.com/docs/expression_language/cookbook/

什么是智能体(Agent)

将大语言模型作为一个推理引擎, 给定一个任务,智能体自动生成完成任务所需的步骤,执行相应动作(例如选择并调用工具),直到任务完成。

先定义一些工具:Tools

  1. 可以是一个函数或三方 API
  2. 也可以把一个 Chain 或者 Agent 的 run()作为一个 Tool

下载一个现有的 Prompt 模板

1
2
react_prompt = hub.pull("hwchase17/react")
print(react_prompt.template)

直接定义执行执行调用

1
2
3
4
5
6
7
8
9
10
11
12
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_react_agent

llm = ChatOpenAI(model_name='gpt-4o', temperature=0, model_kwargs={"seed":23})

# 定义一个 agent: 需要大模型、工具集、和 Prompt 模板
agent = create_react_agent(llm, tools, react_prompt)
# 定义一个执行器:需要 agent 对象 和 工具集
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 执行
agent_executor.invoke({"input": "2024年周杰伦的演唱会星期几"})

LangServe

LangServe 用于将 Chain 或者 Runnable 部署成一个 REST API 服务。

1
2
3
4
5
6
# 安装 LangServe
# !pip install --upgrade "langserve[all]"

# 也可以只安装一端
# !pip install "langserve[client]"
# !pip install "langserve[server]"

LangChain.js

Python 版 LangChain 的姊妹项目,都是由 Harrison Chase 主理。

项目地址:https://github.com/langchain-ai/langchainjs

文档地址:https://js.langchain.com/docs/

特色:

  1. 可以和 Python 版 LangChain 无缝对接
  2. 抽象设计完全相同,概念一一对应
  3. 所有对象序列化后都能跨语言使用,但 API 差别挺大,不过在努力对齐

支持环境:

  1. Node.js (ESM and CommonJS) - 18.x, 19.x, 20.x
  2. Cloudflare Workers
  3. Vercel / Next.js (Browser, Serverless and Edge functions)
  4. Supabase Edge Functions
  5. Browser
  6. Deno

安装:

1
npm install langchain

当前重点:

  1. 追上 Python 版的能力(甚至为此做了一个基于 gpt-3.5-turbo 的代码翻译器)
  2. 保持兼容尽可能多的环境
  3. 对质量关注不多,随时间自然能解决

LangChain 与 LlamaIndex 的错位竞争

  1. LangChain 侧重与 LLM 本身交互的封装
    • Prompt、LLM、Memory、OutputParser 等工具丰富
    • 在数据处理和 RAG 方面提供的工具相对粗糙
    • 主打 LCEL 流程封装
    • 配套 Agent、LangGraph 等智能体与工作流工具
    • 另有 LangServe 部署工具和 LangSmith 监控调试工具
  2. LlamaIndex 侧重与数据交互的封装
    • 数据加载、切割、索引、检索、排序等相关工具丰富
    • Prompt、LLM 等底层封装相对单薄
    • 配套实现 RAG 相关工具
    • 有 Agent 相关工具,不突出
  3. LlamaIndex 为 LangChain 提供了集成