8.让大模型做聊天机器人,那些套壳网站就是这么做的
上一篇文章,我们用OpenAI的Completion接口实现了一个聊天机器人,由于Completion接口对Token数的限制,需要手动管理聊天记录,除此之外,对接口的调用以及参数设置也需要自己完成。
于是,开源社区就有人将这些常见的需求和模式抽象了出来,开发了一个叫做Langchain的开源库。
链式调用
Langchain的第一大卖点就是链式调用,它类似数据结构中的链表,或者工厂中的流水线。
举个例子,像ChatGPT这种大模型,训练数据主要是英文语料,如果用中文提问,效果就会受影响。这时就可以采用链式调用的思想,先将中文翻译成英文,然后再将英文传递给大模型,最后将大模型输出的英文翻译成中文反馈给用户。
接下来使用Langchain中的LLMChain实现这个链式调用过程。
结果:
不过如果看上面这段代码,似乎只是对OpenAI的API以及Prompt格式化做了一层封装而已。构建了3个LLMChain,然后按照顺序调用,每次拿到答案之后,再作为输入,交给下一个LLM调用。感觉好像更麻烦了,没有减少什么工作量呀?
别着急,这是因为我们还没有真正用上LLMChain的“链式调用”功能,要用这个功能,只需要加上一行小小的代码。我们用一个叫做SimpleSequentialChain的LLMChain类,把我们要按照顺序依次调用的三个LLMChain放在一个数组里,传给这个类的构造函数。
结果:
用LLMChain教你重新做机器人
除了链式调用,LLMChain另一个核心功能是它具有记忆力,这正是我们之前的多轮对话机器人所需要的。
前面我们说过,为了实现多轮对话,需要把之前的聊天记录作为上下文传递给大模型。而接口对Token数又是有限制的,所以需要手动删除过期的聊天记录。
BufferWindow,滑动窗口记忆
在LangChain中,我们可以使用BufferWindow来实现滑动窗口记忆,把整个对话内容叫做Memory。任何一个LLMChain,我们都可以给它加上一个Memory,来让它记住最近的对话上下文。
结果:
上面我们在定义ConversationBufferWindowMemory的时候定义了k=3,也就是只保留最近三轮的对话内容。k的值需要根据大模型支持的上下文长度设置。
SummaryMemory,把小结作为历史记忆
使用 BufferWindow 这样的滑动窗口有一个坏处,就是几轮对话之后,AI 就把一开始聊的内容给忘了。遇到这种情况,可以让 AI 去总结一下前面几轮对话的内容。这样,我们就不怕对话轮数太多或者太长了。
同样的,Langchain 也提供了一个ConversationSummaryMemory,可以实现这样的功能。
代码中有一点需要注意:定义 ConversationSummaryMemory时需要一个LLM对象。这个LLM对象是专门用来总结历史对话的,和对话本身使用的LLM是不同的。
总结:
本文介绍了Langchain中的两大核心功能:LLMChain和Memory,用链式调用实现了一个中文问答系统,用记忆力功能重新实现了聊天机器人。