数据库运维工作量直接减少 50%,基于大模型构建智能问答系统的技术分享
为了提供更加丰富和准确的答案,我们采用了一种搜索和推荐系统的方法,并结合了大型模型的推理和总结能力。为了确保准确性和效率,我们选择了第 2 种和第 3 种方式相结合的方案,通过向量数据库将知识外挂作为大模型记忆体,使用 LangChain 作为基础开发框架来构建知识库问答系统,最终依靠 Prompt 工程和大模型进行交互。传统的运维知识库系统主要采用固化的规则和策略来记录管理操作和维护的知识,这些
本文源自百度智能云数据库运维团队的实践,深入探讨了基于大模型构建「知识库智能问答系统」的设计过程和应用。
全文包括了总体的技术方案选型、各个模块的设计实现、重点难点问题的突破、以及目前的落地场景应用等。
该系统自从内部上线以来,整体的回答准确率达到 80% 以上,数据库运维工作量直接减少 50%:包括 80% 咨询量,以及 20% 工单处理工作。
1 背景
随着大模型的飞速发展, AI 技术开始在更多场景中普及。在数据库运维领域,我们的目标是将专家系统和 AI 原生技术相融合,帮助数据库运维工程师高效获取数据库知识,并做出快速准确的运维决策。
传统的运维知识库系统主要采用固化的规则和策略来记录管理操作和维护的知识,这些系统的知识检索方式主要基于关键字搜索和预定义的标签或分类,用户需要具备一定的专业知识才能有效地利用这些系统。
这已不足以满足现在复杂多变的运维环境。因此,借助大模型来提供运维知识并协助决策成为趋势。这将在运维能力、成本控制、效率提升和安全性等方面带来深刻的变革。
在数据库领域,AI 技术应用可以划分为不同场景,例如知识库学习(包括知识问答和知识管理)、诊断与推理(包括日志分析和故障诊断)、工作辅助(包括 SQL 生成和 SQL 优化)等。本文将主要着重介绍「知识库智能问答系统」的设计与实现,旨在为读者提供深入了解该领域应用的思路。
2 架构设计和实现
2.1 技术方案选型
目前,大模型已经可以通过对自然语言的理解揣摩用户意图,并对原始知识进行汇总、整合,进而生成更具逻辑和完整性的答案。然而,仍存在以下几个问题,导致我们不能直接使用这些模型来对特定领域知识进行问答。
- 专业性不足:作为通用大模型,对专业领域知识的训练不足,可能会产生虚假陈述、准确性不足以及信息丰富度不足的问题。
- 时效性问题:模型的训练数据基于某个时间之前的数据,缺乏最新的信息,每次添加新数据都会导致高昂的训练成本。
- 安全性问题:模型无法访问企业内部私密文档,且这些文档不能直接用于 Fine-Tuning。
为了解决这些问题,业界采用了如下几种技术手段来为大型模型提供额外知识。
- Fine-Tuning(微调):使用特定领域的知识对基础大模型进行微调,以改变神经网络参数的权重。虽然适用于特定任务或风格,但需要大量资源和高质量的训练数据。
- Prompt 工程:将行业领域的知识作为输入消息提供给模型,让模型对消息中的知识进行分析和处理。这种方法在正确性和精度上表现良好,但有文本长度限制,对于大规模数据不够高效。
- 与传统搜索结合:使用传统搜索技术构建基础知识库,然后使用大语言模型处理用户请求,对召回结果进行二次加工。这种方法具有更高的可控性和效率,并适用于大规模数据。
为了确保准确性和效率,我们选择了第 2 种和第 3 种方式相结合的方案,通过向量数据库将知识外挂作为大模型记忆体,使用 LangChain 作为基础开发框架来构建知识库问答系统,最终依靠 Prompt 工程和大模型进行交互。
2.2 分模块设计实现
数据库运维知识库的整体设计流程如下图所示,包括文档加载、文档分割、文本/问题向量化、问答缓存、大模型生成答案等流程。
2.2.1 知识入库
- 数据源加载和解析:主要使用 LangChain 支持的文档加载方法,对 PDF、CSV、Markdown 等格式的文档类型进行加载和采集。此外,考虑到很多企业的文档来源是内网网页,因此也支持 Selenium 和 BeautifulSoup 来爬取网页内容,最后再应用 LangChain 中的 Markdown 加载器进行格式解析。
- 文本分片:原始知识库应当被拆分成独立、较短的文本块,每个文本块将作为问答的最小记录,与问题进行匹配。文本的切分质量直接关系到 Embedding 和召回的质量。切分块不能太大或者太小,也不能超过 Embedding 和大模型的 token 限制。在很多内部网页文档中,由于多级标题和段落间是有上下文关联的,所以我们采用 Markdown 或者 HTML 方式进行切分,进而大大提高了对文档内容的感知能力。在文本切分器的选择上,我们主要采用 LangChain 中的 RecursiveCharacterTextSplitter 和 SpacyTextSplitter这两种分词器。它们能够在保持知识点完整性的基础上,对中文句子、段落、章节等进行良好的切分。需要注意的是,由于算法有 token 数量的限制,选择好的分词器能够为切片提供很好的切分单位和依据。目前我们选择的是 tiktoken 和 Spacy 中的 Tokenizer,但有时候并不理想,需要根据大模型采用的 token 计算方法进行适配。
- 文本向量化:在项目初期 Embedding 模型选择了 Hugging Face 上开源的 Embedding模型,例如 GanymedeNil/text2vec-large-chinese和 moka-ai/m3e-large,但实际测试效果并不理想。最终我们选择了文心的 Embeddings 模型,效果有质的飞跃,虽然支持的 token 和向量维度低,但整体效果很好。LangChain 中对于千帆接口进行了封装,可以直接通过百度智能云千帆大模型平台调用文心 Embedding。关于文本向量化、存储和检索的详细信息,请参考下图:
- 存储:将生成的Embeddings(向量)与原始分片(知识点)进行存储,同时考虑存储一些关键的元信息,如链接地址和分片大小,以用于检索时作为过滤条件。专业的解决方案是使用向量数据库,但也可以考虑传统数据库或存储中间件,如RedisSearch 或 pgvector,它们都支持向量字段和向量相似性查询,可提供实时向量索引和查询功能。在向量数据库选型上我们对 ElasticSearch、Baidu ElasticSearch(BES)、Milvus 和 PGVector分别做了测试,在查询性能方面,PostgreSQL 性能较差不可用,而 BES、ES、milvus 性能在一个层级,BES采用自研的插件实现了 HNSW 算法,召回效果表现更好。在资源消耗方面,它们都较为耗费内存,其中 BES 和 ES 相对来说消耗较小。BES 是百度智能云自研的分布式、开源搜索与分析引擎,在百度内部多模态和大模型基础平台有多年积累和应用,在性能、分布式和易用性方面表现良好,LangChain 也对其进行了集成,最终我们选择了 BES 作为向量数据库。
2.2.2 数据检索
- 用户问题向量化:对用户的问题进行向量化计算。如果结果在缓存中命中,将从缓存中获取已经缓存的答案,以减少文心大模型 API 费用和提高响应速度,可使用 GPTCache 等库来实现。
- 向量检索:使用 Embeddings 模型在向量数据库中进行相似性计算,召回相似度最高的 n 个分片。目前设置的召回策略是默认选择前 10 个评分最高的分片。
2.2.3 结果整合
将向量数据库检索召回的文本进行二次加工后,利用 LLM 总结概括和分析推理能力,完成最终答案的生成。
- Prompt 生成:将 n 个切片和用户原始 Question 组装成 Prompt。需要注意的是,Prompt 不能超出 Token 限制,超出限制则需要进行优化,例如淘汰或多次迭代调用等。我们在 Prompt 中除了原始问题和内容,还对大模型加入了回答内容的限制,如「不允许在答案中添加编造成分」、「请用中文回答」等。此外,我们还提供记忆功能,将历史会话信息传入 Prompt,一并发送给大模型。
- 大模型响应:将 Prompt 发送给大模型,获取最终的结果。同时,将对话信息和结果追加存储到 MySQL 中,以保存会话历史,这有助于会话重启和历史信息接入大模型。
3 技术难点和解决方案
3.1 难点一:向量数据库召回率低
尽管通过将知识嵌入(Embedding)与大型语言模型相结合已经成为一种高效的实现路径,但向量数据库在向量化、存储和检索等多个阶段都可能存在问题,进而导致检索结果的召回率不尽如人意。在实际测试中,我们在未经优化的情况下,召回率仅达到了 70% 左右。而一个相对可靠的系统,召回率至少需要达到 85% 或甚至 90% 以上。以下是我们在应用中采取的优化措施。
3.1.1 精确切分文本
- 分割模型:由于训练的文档主要是中文文档,因此切片工具必须具备对中文的良好支持。为此,我们首选 Spacy 作为分割工具,并采用 zh_core_web_sm 模型作为标记器(tokenizer)。
- 分割条件:一般情况下,大部分系统会使用 LangChain 定长切分,但这样会丢失大部分上下文关联,知识点也是割裂的。在实践中,我们没有仅仅依赖 chunk size 作为唯一的切割条件,而是对那些具有明显段落或章节结构的文本格式(如 Markdown 或 HTML)进行了格式化分割,以确保文本的连续性、相关性和完整性。当段落超过 Embedding token 数限制时,我们会使用 RecursiveCharacterTextSplitter 对段落继续进行切分,切分条件除了设置换行符外,还加入了中文常见的断句符号,比如分号、叹号等。
- 标题补偿:当某段文字的大小超过了 chunk size 时,我们会针对没有标题的 chunk 补充标题,以确保整体切分的完整性。
3.1.2 优化文本向量化
- 标题向量化:在进行精细化切分之后,标题的重要性显现出来。因此,我们在这一阶段对标题进行向量化处理。这一方法适用于帮助手册、 HTML 和 Markdown 等文本格式。
- 内容关键字向量化:如果仅对标题进行向量化,对于那些标题概括性较差或段落内容丰富的情况,精召率提升仍然有限。因此,我们还尝试了了另一种方法,即首先利用大型模型或关键字模型提取关键字,数量通常限制在 10 左右,然后对这些关键字进行向量化处理。由于多轮次调用的耗时和关键字提取的可靠性问题,最终该方案被放弃。
- 标题 + 内容同时向量化:在文本分割时,我们强行对每个分片加入了标题。在向量化时,会将标题 + 内容打包一并进行向量化。我们将用户提问向量化后,和向量化后的切片进行检索匹配,选择与问题最相关的 topN 切片,这样可以显著提高精召率,这也是我们最终的方案。
3.1.3 Embeddings 和向量检索调优
对于 Embeddings 的选择和调优,上文已经介绍过,我们最终选择了效果更好的文心 Embedding。对于向量数据库检索性能,这里优化空间并不大,调整 HNSW 算法的参数,对最后召回结果影响不大。
3.2 难点二:Token 数量限制
在应用大型语言模型时,我们面临的主要限制之一就是输入文本的上下文长度。开源模型和商业模型的上下文长度限制范围从 2K 到 100K 不等。上下文长度对于应用大型语言模型具有关键影响,包括知识增强、记忆等方面的工作,都是为了解决上下文长度限制而设计的。以下是我们采取的策略:
- 取舍:如果选择的 10 个文本组合成的 Prompt 超出了模型的 Token 限制,我们采取逐一舍弃相似度较低的片段的策略。如果减少到召回文档为 6 个时还是超限制,则会选择 token 数支持更多的模型。
- 模型选择:ERNIE-Bot-turbo 模型支持 10200 个Token,ERNIE-Bot 支持 2000 个 Token 的 ERNIE-Bot 模型,以扩大上下文长度。但是 ERNIE-Bot-turbo 在问答领域的效果并不如 ERNIE-Bot,此时,我们的策略是在不超过 2000 个 token 的情况下优先选择 ERNIE-Bot,极大地提升了系统对复杂问题的处理能力。
- 压缩 Prompt:我们尝试对多个切片拼接后的文本进行压缩,以提取主要内容,去除无用且重复的词组。然而,这种方法的效果有限,甚至可能导致文本失真,且对中文支持较差,因此无法从根本上解决问题。压缩效果如下图:
- 多轮次迭代调用 LLM:面对超长文本超出大模型 token 限制的情况,我们采用了 MapReduce 的方式来突破 Token 限制。该方式将文本拆分成多个部分,并多次调用 LLM 以解决文本长度问题。具体流程包括将多个分段分别请求 LLM,获取各自的局部答案。然后将这些局部答案拼接成新的 Prompt,再次请求 LLM 以获取最终答案。这一流程有效地扩展了上下文长度,但是实际应用效果并不理想,表现为最终结果失真,尤其是在回答流程类问题场景下。主要原因是汇聚后丢失了很多原始文本细节。
3.3 难点三:知识陈旧和虚构答案
在商业大型模型的大多数应用场景下,模型能够为 MySQL、Oracle 等数据库的相关问题提供令人满意的答案。然而,不可避免地,这些大型模型有时会出现知识陈旧和答案虚构的问题。为了提供更加丰富和准确的答案,我们采用了一种搜索和推荐系统的方法,并结合了大型模型的推理和总结能力。以下是我们的主要方案和流程:
- 提取问题关键字:首先从客户问题中提取关键字,以确保这些关键字能够准确地用于搜索引擎检索。为此,我们探索了两种不同的方法:
- 大模型:大型模型本身具备一定的关键字提取能力,但实际测试表明,这种方法的稳定性有待提高,可能会导致调用链出现异常。因此,我们需要对这种方式进行 Prompt 的调优,以提高其性能和可靠性。
- NLP 算法:另一种思路是利用 NLP 模型来进行关键字提取。然而,我们曾尝试使用 Hugging Face 的一些模型,但效果并不十分理想。
- 搜索引擎检索和文档解析:为了获得与数据库问题相关的准确答案,我们评估了以下两种不同的策略:
- 接入百度搜索引擎:我们曾尝试使用百度搜索 API 来根据提取的关键字进行检索。然而,这一方法的答案质量较差,而且可能包含过时的信息,这可能会对最终答案造成负面影响。因此,我们最终放弃了这一方案。
- 接入官方文档搜索:对于 MySQL 等数据库,官方文档提供了用于客户搜索的 API。我们只需传入关键字即可获取与之匹配的搜索结果。然后,我们可以选择最相关的前 N 个结果,并对这些结果的链接内容进行爬取和解析。这一流程类似于之前描述的领域知识入库和知识检索流程,但具体细节不再赘述。
- 调用大模型:将多个 chunk 拼接和问题一起生成 prompt,调用大模型获取答案。
可以看到文档解析和大模型调用其实就是在重复我们前边介绍的领域知识入库和结果的二次整合过程,唯一不同的地方就是我们使用搜索引擎去代替了向量检索。以 MySQL 为例子,具体流程如下:
4 应用场景接入
该系统自从内部上线以来,整体的回答准确率达到 80% 以上,数据库运维工作量直接减少 50%,包括 80% 咨询量,以及 20% 工单处理工作。
目前「知识库智能问答系统」主要通过两种方式接入和应用:Database Chat 和 IM 机器人。
- Database Chat:除了类似于 ChatGPT 问答界面外,还具备知识管理、用户管理等功能。(该功能已经集成数据库智能驾驶舱 DBSC 中,将于 3 月底正式开放上线)
- IM 机器人:IM 工具做为工作协同中最重要的软件,使用频率非常高。我们提供了 IM 接入接口,客户可以开发 IM 软件(微信、飞书、如流等)机器人,在聊天群中实现快速高效获取信息和知识。
5 总结
从技术工程角度来看,利用向量数据库结合大型 AI 模型来构建领域知识库系统的实现并不复杂,然而,这一领域仍然面临着不少挑战和潜在的改进空间。在本文中,我们已经讨论了一些解决方案和技术,但仍然有许多可能的改进和未来发展方向值得深入研究。
首先我们认为关键点还是解决向量检索的召回准确性和超长文本处理能力是两个难点,这些方面可能还有更好的方式。此外,大模型本身的能力和文档质量是系统性能的关键因素,因此需要不断升级和维护模型,同时确保文档的及时性和准确性。
我们希望更多的研究者和工程师积极贡献更多的创新思路和技术,推动大模型在数据库运维领域落地,期待未来能有更多的可能性。
更多推荐
所有评论(0)