9善用LangChain中的链式调用和记忆力,简化大模型应用开发
作者: 人工智能大讲堂 来源: 人工智能大讲堂
上一篇文章,我们用OpenAI的Completion接口实现了一个聊天机器人,由于Completion接口对Token数的限制,需要手动管理聊天记录,除此之外,对接口的调用以及参数设置也需要自己完成。
于是,开源社区就有人将这些常见的需求和模式抽象了出来,开发了一个叫做Langchain的开源库。
链式调用
Langchain的第一大卖点就是链式调用,它类似数据结构中的链表,或者工厂中的流水线。
举个例子,像ChatGPT这种大模型,训练数据主要是英文语料,如果用中文提问,效果就会受影响。这时就可以采用链式调用的思想,先将中文翻译成英文,然后再将英文传递给大模型,最后将大模型输出的英文翻译成中文反馈给用户。
接下来使用Langchain中的LLMChain实现这个链式调用过程。
import openai, os
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI
from langchain.chains import LLMChain
openai.api_key = os.environ.get("OPENAI_API_KEY")
llm = OpenAI(model_name="text-davinci-003", max_tokens=2048, temperature=0.5)
en_to_zh_prompt = PromptTemplate(
template="请把下面这句话翻译成英文:\n\n {question}?", input_variables=["question"]
)
question_prompt = PromptTemplate(
template = "{english_question}", input_variables=["english_question"]
)
zh_to_cn_prompt = PromptTemplate(
input_variables=["english_answer"],
template="请把下面这一段翻译成中文:\n\n{english_answer}?",
)
question_translate_chain = LLMChain(llm=llm, prompt=en_to_zh_prompt, output_key="english_question")
english = question_translate_chain.run(question="请你作为一个机器学习的专家,介绍一下CNN的原理。")
print(english)
qa_chain = LLMChain(llm=llm, prompt=question_prompt, output_key="english_answer")
english_answer = qa_chain.run(english_question=english)
print(english_answer)
answer_translate_chain = LLMChain(llm=llm, prompt=zh_to_cn_prompt)
answer = answer_translate_chain.run(english_answer=english_answer)
print(answer)
结果:
Please explain the principles of CNN as an expert in Machine Learning.
A Convolutional Neural Network (CNN) is a type of deep learning algorithm that is used to analyze visual imagery. It is modeled after the structure of the human visual cortex and is composed of multiple layers of neurons that process and extract features from an image. The main principle behind a CNN is that it uses convolutional layers to detect patterns in an image. Each convolutional layer is comprised of a set of filters that detect specific features in an image. These filters are then used to extract features from the image and create a feature map. The feature map is then passed through a pooling layer which reduces the size of the feature map and helps to identify the most important features in the image. Finally, the feature map is passed through a fully-connected layer which classifies the image and outputs the result.
卷积神经网络(CNN)是一种深度学习算法,用于分析视觉图像。它模仿人类视觉皮层的结构,由多层神经元组成,可以处理和提取图像中的特征。CNN的主要原理是使用卷积层来检测图像中的模式。每个卷积层由一组滤波器组成,可以检测图像中的特定特征。然后使用这些滤波器从图像中提取特征,并创建特征图。然后,将特征图通过池化层传递,该层可以减小特征图的大小,并有助于识别图像中最重要的特征。最后,将特征图传递给完全连接的层,该层将对图像进行分类,并输出结果。
不过如果看上面这段代码,似乎只是对OpenAI的API以及Prompt格式化做了一层封装而已。构建了3个LLMChain,然后按照顺序调用,每次拿到答案之后,再作为输入,交给下一个LLM调用。感觉好像更麻烦了,没有减少什么工作量呀?
别着急,这是因为我们还没有真正用上LLMChain的“链式调用”功能,要用这个功能,只需要加上一行小小的代码。我们用一个叫做SimpleSequentialChain的LLMChain类,把我们要按照顺序依次调用的三个LLMChain放在一个数组里,传给这个类的构造函数。
from langchain.chains import SimpleSequentialChain
chinese_qa_chain = SimpleSequentialChain(
chains=[question_translate_chain, qa_chain, answer_translate_chain], input_key="question",
verbose=True)
answer = chinese_qa_chain.run(question="请你作为一个机器学习的专家,介绍一下CNN的原理。")
print(answer)
结果:
卷积神经网络(CNN)是一种常用于图像识别和分类任务的人工神经网络。它们受到人脑结构的启发,由多层神经元以特定模式连接而成。CNN的第一层神经元与输入图像连接,最后一层神经元与输出连接。输入和输出层之间的神经元称为特征映射,负责从输入图像中提取特征。CNN使用卷积层检测输入图像中的模式,使用池化层减小特征映射的大小。这使得CNN能够学习图像中最重要的特征,并利用它们进行预测。
用LLMChain教你重新做机器人
除了链式调用,LLMChain另一个核心功能是它具有记忆力,这正是我们之前的多轮对话机器人所需要的。
前面我们说过,为了实现多轮对话,需要把之前的聊天记录作为上下文传递给大模型。而接口对Token数又是有限制的,所以需要手动删除过期的聊天记录。
BufferWindow,滑动窗口记忆
在LangChain中,我们可以使用BufferWindow来实现滑动窗口记忆,把整个对话内容叫做Memory。任何一个LLMChain,我们都可以给它加上一个Memory,来让它记住最近的对话上下文。
from langchain.memory import ConversationBufferWindowMemory
template = """你是一个中国厨师,用中文回答做菜的问题。你的回答需要满足以下要求:
1. 你的回答必须是中文
2. 回答限制在100个字以内
{chat_history}
Human: {human_input}
Chatbot:"""
prompt = PromptTemplate(
input_variables=["chat_history", "human_input"],
template=template
)
memory = ConversationBufferWindowMemory(memory_key="chat_history", k=3)
llm_chain = LLMChain(
llm=OpenAI(),
prompt=prompt,
memory=memory,
verbose=True
)
llm_chain.predict(human_input="你是谁?")
结果:
' 我是一个中国厨师,我可以帮助你做菜。我会根据你的口味和特殊要求,精心烹饪出独特美味的中国菜肴。'
上面我们在定义ConversationBufferWindowMemory的时候定义了k=3,也就是只保留最近三轮的对话内容。k的值需要根据大模型支持的上下文长度设置。
SummaryMemory,把小结作为历史记忆
使用 BufferWindow 这样的滑动窗口有一个坏处,就是几轮对话之后,AI 就把一开始聊的内容给忘了。遇到这种情况,可以让 AI 去总结一下前面几轮对话的内容。这样,我们就不怕对话轮数太多或者太长了。
同样的,Langchain 也提供了一个ConversationSummaryMemory,可以实现这样的功能。
代码中有一点需要注意:定义 ConversationSummaryMemory时需要一个LLM对象。这个LLM对象是专门用来总结历史对话的,和对话本身使用的LLM是不同的。
from langchain.chains import ConversationChain
from langchain.memory import ConversationSummaryMemory
llm = OpenAI(temperature=0)
memory = ConversationSummaryMemory(llm=OpenAI())
prompt_template = """你是一个中国厨师,用中文回答做菜的问题。你的回答需要满足以下要求:
1. 你的回答必须是中文
2. 回答限制在100个字以内
{history}
Human: {input}
AI:"""
prompt = PromptTemplate(
input_variables=["history", "input"], template=prompt_template
)
conversation_with_summary = ConversationChain(
llm=llm,
memory=memory,
prompt=prompt,
verbose=True
)
conversation_with_summary.predict(input="你好")
总结:
本文介绍了Langchain中的两大核心功能:LLMChain和Memory,用链式调用实现了一个中文问答系统,用记忆力功能重新实现了聊天机器人。
更多AI工具,参考Github-AiBard123,国内AiBard123