前言
推荐大家看看:
在开发自己的Agent时,可以让AI去参考这里面的内容,让AI更聚焦,减少出现幻觉的情况。
一、必知概念
Loader 加载器
就是用于加载各类数据的,网页、PDF、文件夹等等。
Document 文档
当使用loader加载器读取到数据源后,数据源需要转换成 Document 对象后,后续才能进行使用。
Text Spltters 文本分割
就是用来分割文本的。由于LLM字符限制,一次发送过多的字符会报错。
Vectorstores 向量数据库
由于数据相关性搜索实则是向量运算。所以需要将加载的数据 Document 进行向量化,才能进行向量运算搜索。转换成向量也很简单,只需要我们把数据存储到对应的向量数据库中即可完成向量的转换。
Chain 链
我们可以把 Chain 理解为任务。一个 Chain 就是一个任务,当然也可以像链条一样,一个一个的执行多个链。
Agent 代理

Embedding
用于衡量文本的相关性。这个也是 OpenAI API 能实现构建自己知识库的关键所在。
他相比 fine-tuning 最大的优势就是,不用进行训练,并且可以实时添加新的内容,而不用加一次新的内容就训练一次,并且各方面成本要比 fine-tuning 低许多。
二、通过 Google 搜索并返回答案
Serpapi 提供了 google 搜索的 api 接口。
第一需要我们到 Serpapi 官网上注册一个用户, 并复制他给我们生成 api key。
然后我们需要像上面的 openai api key 一样设置到环境变量里面去。
从下面的代码中可以看出:serpapi搜索功能就是使用一个外部工具实现的。
import os
os.environ["OPENAI_API_KEY"] = '你的api key'
os.environ["SERPAPI_API_KEY"] = '你的api key'
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.llms import OpenAI
from langchain.agents import AgentType
# 加载 OpenAI 模型
llm = OpenAI(temperature=0,max_tokens=2048)
# 加载 serpapi 工具
tools = load_tools(["serpapi"])
# 如果搜索完想再计算一下可以这么写
# tools = load_tools(['serpapi', 'llm-math'], llm=llm)
# 如果搜索完想再让他再用python的print做点简单的计算,可以这样写
# tools=load_tools(["serpapi","python_repl"])
# 工具加载后都需要初始化,verbose 参数为 True,会打印全部的执行详情
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
# 运行 agent
agent.run("What's the date today? What great events have taken place today in history?")
在 chain 和 agent 对象上都会有 verbose 这个参数,这个是个超级有用的参数,开启他后我们可以看到完整的 chain 执行过程。
可以在上面返回的结果看到,他将我们的问题拆分成了几个步骤,然后一步一步得到最终的答案。
关于agent type 几个选项的含义:
- zero-shot-react-description: 根据工具的描述和请求内容的来决定使用哪个工具(最常用)
- react-docstore: 使用 ReAct 框架和 docstore 交互, 使用
Search和Lookup工具, 前者用来搜, 后者寻找term, 举例:Wipipedia工具 - self-ask-with-search 此代理只使用一个工具: Intermediate Answer, 它会为问题寻找实际答案(指的非 gpt 生成的答案, 而是在网络中,文本中已存在的), 如
Google search API工具 - conversational-react-description: 为会话设置而设计的代理, 它的prompt会被设计的具有会话性, 且还是会使用 ReAct 框架来决定使用来个工具, 并且将过往的会话交互存入内存
三、超长文本总结
如果遇到了超长文本的情况,LLM最大token限制报错;我自己第一想到的就是拆分,把文本拆成几段,对每一段进行总结,最后再把各段总结整合在一起,实现一种压缩的效果。
Langchain中实现这个过程就简单的多了:
代码看看知道大致的逻辑即可,目前AI的各种框架更新很快。
from langchain.document_loaders import UnstructuredFileLoader
from langchain.chains.summarize import load_summarize_chain
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain import OpenAI
# 导入文本
loader = UnstructuredFileLoader("/content/sample_data/data/lg_test.txt")
# 将文本转成 Document 对象
document = loader.load()
print(f'documents:{len(document)}')
# 初始化文本分割器
text_splitter = RecursiveCharacterTextSplitter(
chunk_size = 500,
chunk_overlap = 0
)
# 切分文本
split_documents = text_splitter.split_documents(document)
print(f'documents:{len(split_documents)}')
# 加载 llm 模型
llm = OpenAI(model_name="text-davinci-003", max_tokens=1500)
# 创建总结链
chain = load_summarize_chain(llm, chain_type="refine", verbose=True)
# 执行总结链,(为了快速演示,只总结前5段)
chain.run(split_documents[:5])





