LangChain 上手记录,从实战开始
type
status
date
slug
summary
tags
category
icon
password
最近研究 LangChain 但又不想费 token,注意到 FastChat 的 OpenAI 兼容 API服务器可以无缝地将 LangChain 与开放模型一起使用。LangChain 发展迅速,最近(2023.8.25)实践过程中发现对比之前的一个教程有了一些差异,对于私有部署的模型坑相对更多,于是记录如下(如果使用 OpenAI API 可忽略第一步 FastChat 兼容):
FastChat 兼容
首先启动 controller,然后根据本地模型路径
--model-path
启动 model_worker,映射到 OpenAI 官方支持的模型名字,再启动 RESTful API 服务器:TODO:探究这里启动模型时是如何映射的
然后设置 OpenAI 环境变量,从本地部署的端口访问模型,因为 FastChat 没有 API KEY 的设计,所以直接设置为 EMPTY:
测试例:文档全部输入模型问答(Embedding模型,及文档问答)
如果是在 notebook 中设置环境变量,可以使用 os.environ
最后通过一个问答例子进行 LangChain 测试(注意用 pip install 安装 langchain、openai):
概念解释
- Loader:从指定源加载文件,比如文件夹 DirectoryLoader、CSV文件
CSVLoader
、Google网盘GoogleDriveLoader
、任意的网页UnstructuredHTMLLoader
、PDFPyPDFLoader
等
- Document:Loader 读取数据后需要转成 Document 才能继续使用
- Text Splitter:字面意思,用来分割文本,限制 Prompt 长度
- Vectorstores:将 Document 存储到向量数据库,以便进行 Retrive 等操作
- Agent & Chain:Chain 是一系列按照特定顺序执行的步骤,每个步骤可以是一个工具或者语言模型的调用,而 Agent 是控制 Chain 执行的实体,它可以根据输入和上一个步骤的输出来决定下一个步骤应该是什么。
实战例子
基本问答(模型 + schema)
普通模型和聊天模型基础:
- ChatOpenAI 聊天模型下,使用 schema 中的
SystemMessage
等将字符串变成符合 OpenAI API 的规范;
- ChatOpenAI 聊天模型也可以通过调用 predict 作普通模型使用;
- 普通模型直接调用模型补全,如果本地部署的是 chat 类型的模型,使用 ChatOpenAI 的 predict 模拟普通模型问答效果更佳(初步猜测是 ChatOpenAI 发起的响应更符合 chat 模型训练时的 prompt 【待验证】);
- 除此之外: schema 里的各种 Message 就是将字符串变成规范的 Chat OpenAI API 格式 ,各种 Template 则是在此基础上再封装了一层(类似 f string),可以传入参数动态改变 prompt;
结合 Google 搜索
sepapi key:
使用 google 搜索需要 serpapi key,先自行注册之后设置
Qwen-7B 作为模型支持的答案,我搜了一下,今天的日期是对的,可惜了登月是 1969 年的 7.20,所以后面的话不正确;
有资料说 serpapi 对中文不太友好,不知道是基于模型能力还是 API 搜索到的中文网页质量,抑或是两者都有,毕竟我使用本地模型的情况下,改成英文之后连时间都错了
总结超长文本
准备数据:
先读取文档,然后切分,最后转成 Document 的列表以便 LangChain 处理。初始化切分器时,可以设置 chunk_size 控制片段大小、chunk_overlap 控制片段间的重叠(影响片段上下文关联性)
chain_type:控制如何将 document 送给 llm
stuff
:将所有 document 一次性扔给模型总结,容易超出文本长度
map_reduce
:先将每个 document 进行总结,最后将所有 document 总结出的结果再进行一次总结
refine
:总结当前 document 时,会带着对上一个 document 的总结,理论上会更加连贯
map_rerank
:一般用在问答的 chain 上,依据用户的问题和每个 document 的相似度,将现有的 document 列表排个序,将概率最高的 document 和问题一起放入 prompt 给模型,让模型返回答案;
map_reduce
等方法可以自己重写,也可以自己设置 map_reduce
的 prompt 模版,比如此案例让模型用中文输出摘要;可以看到最终总结效果还是挺通顺的,在我看来已经达到了值得一读,颇有见地的程度😂
基于本地文件问答
踩坑:中途卡在 nltk 的下载,卡了非常久,也不报错就是下载不下来,wget nltk_data 里的文件也不好使,最后把整个 nltk_data clone 下来了,将 packages 文件夹内容复制到 nltk_data 中,然后进去子文件夹中解压(tokenizers taggers 等);
问答总体流程
快速入门
直接使用高级封装
VectorstoreIndexCreator
,使用 index.query
即可简单实现长文问答,(文章表示:使用 query_with_sources
还可以获取涉及的源,但我目前还没试出来什么效果)对网络博文提问:
具体实现流程
高级封装虽然方便但高度抽象,还是看看具体实现过程,首先准备数据,将数据加载到 loader,然后切分,最后存储到
vectorstores
,用 RetirevalQA
生成 chain :代码中,召回和问题相似的 docs 过程如下
深入:除了向量存储检索,还可以在
langchain.retrievers
找到不同方法比如 SVM 等方法召回,以下是用 SVM 召回的例子MultiQueryRetriever
生成输入问题的变体以改进检索。
Max marginal relevance
选择检索到的文档之间的相关性和多样性。
自定义提示:召回可以自定义 Prompt 模版
返回引文:使用
RetrievalQAWithSourcesChain
可以返回引用 source更底层控制:可以选择更低的抽象级别实现更细致的控制,比如对相关文档如何使用(stuff,reduce_map 等)
对话 QA:指定一个
ConversationBufferMemory
来跟踪历史对话内容(记录输入输出);然后在对话召回的 Chain 中使用 Memory Buffer,即可进行对话;数据持久化:Chroma 也能可实现本地持久化存储向量,只需要定义
persist_directory
路径,需要使用的时候可以从该路径加载;此外也可以使用在线向量数据库,比如 Pinecone📎 参考文章
Last update: 2023-08-21
type
status
date
slug
summary
tags
category
icon
password
🎉 欢迎来到我的小站!
📚 这里主要分享记录开发技术和AI知识👀
❤️ 若您认可我的内容,欢迎请我喝杯咖啡~