一.StrOutputParser字符串输出解析器

1.StrOutputParser是LangChain内置的简单字符串解析器

  • 可以将AIMessage解析为简单的字符串,符合了模型invoke方法要求(可传入字符串,不接收AIMessage类型)
  • 是Runnable接口的子类(可以加入链)

parser = StrOutputParser()

chain = prompt | model | parser | model

2.Runnable接口

二.JsonOutputParser&多模型执行链

chain = prompt | model | parser | model | parser

在前面我们完成了这样的需求去构建多模型链,不过这种做法并不标准,因为:

上一个模型的输出,没有被处理就输入下一个模型。

正常情况下我们应该有如下处理逻辑:

invoke|stream 初始输入  提示词模板  模型  数据处理  提示词模板  模型  解析器  结果

即: 上一个模型的输出结果,应该作为提示词模版的输入,构建下一个提示词,用来二次调用模型。

  • 模型的输出为:AIMessage类对象
  • 提示词模板要求输入:dict类对象

所以,我们需要完成: 将模型输出的AIMessage  转为字典  注入第二个提示词模板中,形成新的提示词(PromptValue对象)

  • 模型输入:PromptValue或字符串或序列(BaseMessage、list、tuple、str、dict)。
  • 模型输出:AIMessage
  • 提示词模板输入:要求是字典
  • 提示词模板输出:PromptValue对象
  • StrOutputParser:AIMessage输入、str输出
  • JsonOutputParser:AIMessage输入、dict输出

三.RunnableLambda&函数加入链

除了JsonOutputParser这类固定功能的解析器之外 我们也可以自己编写Lambda匿名函数来完成自定义逻辑的数据转换,想怎么转换就怎么转换,更自由。 想要完成这个功能,可以基于RunnableLambda类实现。

RunnableLambda类是LangChain内置的,将普通函数等转换为Runnable接口实例,方便自定义函数加入chain。

语法: RunnableLambda(函数对象或lambda匿名函数)

跳过RunnableLambda类,直接让函数加入链也是可以的。

chain = first_prompt | model | (lambda ai_msg: {"name": ai_msg.content}) | second_prompt | model | str_parser

四.Memory

4.1临时会话记忆  InMemoryChatMessageHistory

LangChain提供了History功能,帮助模型在有历史记忆的情况下回答。

  • 基于RunnableWithMessageHistory在原有链的基础上创建带有历史记录功能的新链(新Runnable实例)
  • 基于InMemoryChatMessageHistory为历史记录提供内存存储(临时用)

4.2长期会话记忆  FileChatMessageHistory

使用InMemoryChatMessageHistory仅可以在内存中临时存储会话记忆,一旦程序退出,则记忆丢失。 InMemoryChatMessageHistory 类继承自 BaseChatMessageHistory

FileChatMessageHistory类实现,核心思路:

  • 基于文件存储会话记录,以session_id为文件名,不同session_id有不同文件存储消息
  • 继承BaseChatMessageHistory实现如下3个方法:
    • add_messages:同步模式,添加消息
    • messages:同步模式,获取消息
    • clear:同步模式,清除消息

五.Document loaders文档加载器

文档加载器提供了一套标准接口,用于将不同来源(如 CSV、PDF 或 JSON等)的数据读取为 LangChain 的文档格式。这确保了无论数据来源如何,都能对其进行一致性处理。 文档加载器(内置或自行实现)需实现BaseLoader接口。

Class Document,是LangChain内文档的统一载体,所有文档加载器最终返回此类的实例。 一个基础的Document类实例,基于如下代码创建:

from langchain_core.documents import Document

document = Document(  

     page_content="Hello, world!", metadata={"source": "https://example.com"}

)

可以看到,Document类其核心记录了:

  • page_content:文档内容
  • metadata:文档元数据(字典)

不同的文档加载器可能定义了不同的参数,但是其都实现了统一的接口(方法)。

  • load():一次性加载全部文档
  • lazy_load():延迟流式传输文档,对大型数据集很有用,避免内存溢出。

5.1CSVLoader

from langchain_community.document_loaders.csv_loader import CSVLoader

loader = CSVLoader(file_path="./xxx.csv")

data = loader.load()

print(data)

自定义CSV文件的解析和加载:

loader = CSVLoader(

    file_path=“./xxx.csv”,

    csv_args={

        “delimiter”: ",",   # 指定分隔符

        “quotechar”: '"'     # 指定字符串的引号包裹

        "fieldnames": ["name", "age", "gender"],   # 字段列表(无表头使用,有表头勿用会读取首行做为数据)

  },

)

data = loader.load()

print(data)

5.2JSONLoader

JSONLoader用于将JSON数据加载为Document类型对象。

使用JSONLoader需要额外安装: pip install jq

from langchain_community.document_loaders import JSONLoader

loader = JSONLoader(

    file_path="xxx.json",   # 文件路径

    jq_schema=".",          # jq schema语法

    text_content=False,     # 抽取的是否是字符串,默认True

    json_lines=True,        # 是否是JsonLines文件(每一行都是JSON的文件)

)

5.3PyPDFLoader

from langchain_community.document_loaders import PyPDFLoader

loader = PyPDFLoader(

    file_path="",   # 文件路径必填

    mode='page',    # 读取模式,可选page(按页面划分不同Document)和single(单个Document)    

password='password', # 文件密码

)

5.4TextLoader和文档分割器

作用:读取文本文件(如.txt),将全部内容放入一个Document对象中。

from langchain_community.document_loaders import TextLoader

loader = TextLoader(

    "xxx.txt",

    encoding="utf-8",

)

docs = loader.load()

print(docs)

print(len(docs))    # 结果为1

如果文档很大 加载到一个Document对象中是否不太合适?

RecursiveCharacterTextSplitter,递归字符文本分割器,主要用于按自然段落分割大文档。 是LangChain官方推荐的默认字符分割器。

六.Vector stores 向量存储

如图,这是一个典型的向量存储应用,也即是典型的RAG流程。

这部分开发主要涉及到:

  • 如何文本转向量(前文已经学习)
  • 创建向量存储,基于向量存储完成:
    • 存入向量         add_documents
    • 删除向量         delete
    • 向量检索         similarity_search

内置向量存储的使用:

外部(Chroma)向量存储的使用:

6.2检索向量并构建提示词

向量存储的实例,通过add_texts(list[str])方法可以快速添加到向量存储中。

vector_store.add_texts(["减肥就是要少吃多练","在减脂期吃东西很重要,清单少有控制卡路里","跑步是很好的运动"])

流程:

  1. 先通过向量存储检索匹配信息
  2. 将用户提问和匹配信息一同封装到提示词模板中提问模型

6.3RunnablePassthrough的使用

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐