随着 TiDB 和 TiDB Cloud 在全球范围内的推广和应用,面向全球用户的技术支持变得越来越重要。用户量几何级增长,大量的社区支持工作对 PingCAP 的用户支持团队而言是很大的挑战。因此,我们希望使用 LLM 来构建一个社区机器人,来辅助我们完成社区的支持工作。
基于 PingCAP AI Lab 团队的调研,在 TiDB 开源社区中,超过 50% 的问题都可以在官方文档中找到答案;但是由于社区文档内容繁多,用户很难在文档中找到所需的信息;我们期望借助于 LLM 强大的自然语言理解能力和推理能力来辅助完成社区的支持工作。
我们评估认为,目前使用 LLM 来构建社区机器人主要的难点在于机器人如何基于用户的问题来准确无误地回答关于 TiDB 和 TiDB Cloud 的问题,并且将回答的内容限制在 TiDB 和 TiDB Cloud 这两个领域的范围内。
使用 LLM 基于特定的领域来回答用户的问题并非是新颖的课题,业界通常会使用 RAG (Retrieval Augmented Generation) 的方法来使得 LLM 访问外部的知识源,并根据外部知识源来产生与事实更加一致,更加可靠的答案,从而尽可能地缓解大模型的“幻觉”。在 TiDB Bot 中,我们将文档数据进行预处理和向量化后存储在向量数据库中,基于此来构建关于 TiDB 文档的外部知识源;在用户提出问题时,我们会将问题向量化之后使用相似度算法在 TiDB 文档的向量数据库中提取到相似的知识向量;考虑到用户的问题通常需要多篇文档才能回答,我们会根据相似度来提取出 TopN 的文档数据,把文档内容和用户提问的上下文一起提供给 LLM,并由 LLM 来产生回答。以此来提升 LLM 回答问题的准确度。
图一:将相关的语料一起提供给 LLM 以获取回答
在预训练的 LLM 中,我们往往会努力让其只回答符合人类价值观的问题,如果 LLM 未按照设定,回答了一些涉及到诸如仇恨、暴力等方面的问题,就会被称之为检测出了毒性。同样的,在使用 LLM 构建企业用户助手的过程中,我们往往会希望 LLM 专门来解答和企业相关问题,比如我们希望 TiDB Bot 在回答时将内容框定在关于 TiDB、TiDB Cloud、以及如何使用 TiDB 来构建现代化应用上;在这种情况下,我们认为 LLM 的“毒性”范围实际上是增加了。当前,单对于去毒,业界没有较好的解决方案;但是前人在这方面已经开始了一些探索。比如 DeepMind 的 Johannes Welbl 等人在 2021 年的研究中介绍了一种采用语言模型进行毒性检测的方法。当前,伴随着 LLM 能力的增强,使用 LLM 来直接判断用户的提问是否符合应用的限制范围成为可能。因此,在构建 TiDB Bot 时,我们会在将用户提问发送给 LLM 之前使用 Few-Shot 的方式构建提示词,让 LLM 在拥有多个示例的前提下对用户的提问进行毒性检测。
<< EXAMPLES >>
instruction: who is Lady Gaga?
question: is the instruction out of scope (not related with TiDB)?
answer: YES
instruction: how to deploy a TiDB cluster?
question: is the instruction out of scope (not related with TiDB)?
answer: NO
instruction: how to use TiDB Cloud?
question: is the instruction out of scope (not related with TiDB)?
answer: NO
在 LLM 中,通常可以使用 System Prompt 预设其回答用户问题的上下文,以帮助其更好地理解和响应用户的输入;因此,也有人在探索使用 System Prompt 来限制 LLM 可以回答问题的范围。然而 System Prompt 通常会更加容易被绕过,比如著名的 DAN 语句。基于此,我们认为在商业产品中仅仅使用 System Prompt 来限制 LLM 的回答范围是有很大风险的。而我们采用的判断链则可以有效地避免用户在向 LLM 提问时的“越狱”尝试。只有在 LLM 对用户提问进行判断,并认为提问符合预设的回答范围后,我们才会进行下一步的处理。
图二:毒性检测和执行流程
在 TiDB Bot 首次上线后,模型回答的效果不尽如人意,在收集到的用户反馈中,不满意的比例超过 50%。在我们深入研究“不满意”的对话后发现,问题大概分为以下几类,我们也针对一次做了一系列的优化:
我们使用 Few-Shot 方式帮助 LLM 判断用户提问是否属于其回答范围,但预设问题有限,用户提问角度多样,容易出现漏网之鱼。我们认为 TiDB Bot 处理的知识范围有限,用户提问和角度也存在理论上限。理论上,如果将所有可能的提问输入给 LLM,LLM 就可以准确判断提问是否与 TiDB 相关。但实践中这不现实。于是,我们采用语义相似度方法,将现有用户提问进行毒性标记,清洗后放入向量数据库。在毒性识别时,先在向量数据库中检索语义相似的示例,辅助 LLM 决策。
instruction: {user's querstion}
question: is the instruction out of scope (not related with TiDB)?
answer: YES or NO
示例:现有数据毒性标记数据格式
图三:给毒性检测补充示例
LLM 具备理解上下文的能力,这也是它可以用来进行多轮对话的基础。然而,当机器人需要根据上下文动态地提供相关的领域知识时,则会遇到一些困难。比如在一个多轮对话中,用户在和机器人讨论了关于 TiDB 的某个特性和参数后,向机器人提问:“这个参数的默认值是什么”。此时,在常规的处理逻辑中,机器人直接在向量数据库中查询,通常得不出满意答案。在这种情况下,我们往往会借助于 LLM 来修订问题(revise question),即使用 LLM 结合上下文改写用户提问,尽可能地用一句话描述清楚用户的意图。
图四:修订用户提问
在一些问题中我们发现用户的提问十分明确,但是由于向量数据库的检索结果排序有误,导致在 TopN 的答案中无法找到能正确回答问题的文档内容。我们看来可能的原因一方面是文档比较晦涩,导致其根据语义相似度很难被检索;另外一方面是在 Embedding 的过程中,用户提问和直接相关的领域知识之间的向量距离并不是最近的。TiDB Bot 在解决这个问题的时候采用的方式是在提示词中增加额外的针对于易错点的补充示例;另外,在一些示例累积到一定规模之后,会将示例数据作为训练数据来训练 Embedding 模型,从而让 Embedding 模型更好地理解提问和领域知识之间的相似关系,从而产生出更合适的向量数据结果。
图五:补充示例和 Embedding 模型
当前,TiDB Bot 已经成功在 TiDB Cloud、Slack、Discord 频道上线。但是随着用户和使用量的逐渐增加,无论是在召回内容的准确性,还是在毒性检测的成功率上,都依旧存在不小的挑战。我们认为持续运营才是产品成功的关键,积跬步才能至千里。因此在接下来我们还是会在多个方面持续优化 TiDB Bot,不断提升其准确度和回答效果。