LLM与本地知识库

目录如下

一些基本概念

知识库为什么需要大模型

使用Llamaindex连接大模型和本地知识库

需要处理的问题

一些基本概念

  • embedding: 嵌入是一种向量表示,用于保留数据(例如一些文本)的内容和/或意义的维度。在某种程度上相似的数据块往往具有更接近的嵌入向量,而不相关的数据则相距较远。
  • tokens: 大模型处理数据的最小单位,一般中文1个字代表一个token, 英文的话一般一个token=0.75个英文单词

知识库为什么需要大模型

我们来看一个日常工作中常见的工作流

  • A: xxxxx, 这个是什么原因啊
  • B: 稍等,我看下哈
    1. 如果【大脑检索】xxxx问题出现过,根据记忆来回答问题
    2. 如果【大脑检索】xxxx问题出现过, 但具体结论之类的忘了,但是记录了文档, 那就需要根据关键词从【文档中检索】
    3. 如果【大脑检索】xxxx问题出现过, 但具体结论之类的忘了,也没有记录文档,那就需要重新根据问题排查问题了
    4. 如果【大脑检索】xxxx问题未出现过, 处理方案同上

上面这个工作流,从耗时来说 1, 2 << 3,4

也是日常工作的非常常见的工作流, 那么这里的问题就转化两个步骤

  1. 为你初次处理此问题的上下文,处理流程是否保存完备
  2. 以及当我们在搜索时, 能够较为方便的搜索到初次处理问题的文档

步骤1 完全靠自己自觉了, 我们可以操作的部分就是步骤2了

步骤2的核心就是搜索了, 有了google/百度搜索工具之后, 人类利用知识的效率大大提升, 可以想象一下,没有搜索引擎之前我们能做什么? 读书/向认识的咨询专家在哪-向专家请求/

有搜索引擎的利好,让整个数字化的流程大大加速。 回到我们的搜索场景, 其实是本地化的, 本地化的搜索逻辑基本上是 利用全文搜索去解决如ELK/confluence。

我们再看看全文搜索的问题, 通过关键词去找关联, 会存在2个问题

  • 关键词必须要匹配
  • 关键词比较短的情况,搜索结果会特别大

那么怎么解决这个问题?

大模型,openai的大模型让我们看到了一个有理解能力和表达能力的超级知识体。

  1. 它掌握了几乎人类公开最精华的知识库了
  2. 它能够理解你的问题, 并基于它的知识库来组织语言回复你

上面描述的2个特性,完美的解决上面全文索引的问题, 在搜索引擎之后, 人类利用知识的效率达到一个新的高度。

其实如果使用大模型与大模型内部的知识库,其实很多什么只能解决通用性问题, 一旦问题涉及到自己的业务领域, 此时就需要把自己业务领域的知识喂给大模型。但是这里涉及几个问题

  • 业务领域数据属于公司自有数据,全部喂给大模型,有数据泄露风险
  • 大模型有token限制 , 目前的GPT-3.5-tubo-16K的限制是16k。 (业务领域的知识远远大于这个数字)

那怎么解决上面的问题呢?

llamada-index

使用Llamaindex连接大模型和本地知识库

image-20230625110946455

llamaIndex 处理什么问题?

提供一系列工具去方便用户去使用llm去调用本地知识库

工具包含: 对于各种大模型的封装 / 对于各种本地知识库的文件文件解析 / embedding模型的支持 / 向量数据库连接的封装

典型流程

  • 用户问了一个问题
  • llamda-index将用户问题(转化为向量)与本地知识库(向量数据库存储) 匹配, 搜索出Top-k 的相关文件片段
  • llamad-index 将搜索用户问题 + 搜索出的相关文件片段 发送给大模型
  • 大模型给出答复

showcode

  • 本地文档如下-markdown文件

    ### 运维常用联系人
    svn负责人:   xxx1
    gitlab负责人:  xxx2
    sonarqube负责人: xxx3
  • 代码如下

    import os
    
    from langchain.llms import OpenAIChat
    
    # 这一步可以不需要,可以把OPENAI_API_KEY 放在环境变量里
    # os.environ["OPENAI_API_KEY"] = ''
    
    from llama_index import GPTVectorStoreIndex, SimpleDirectoryReader, StorageContext, load_index_from_storage, \
        LLMPredictor, ServiceContext
    
    if __name__ == "__main__":
        llm_predictor = LLMPredictor(llm=OpenAIChat(model_name="gpt-3.5-turbo-16k-0613", temperature=0.6, verbose=True))
        service_context = ServiceContext.from_defaults(llm_predictor=llm_predictor)
        if os.path.exists("./storage"):
            # rebuild storage context
            storage_context = StorageContext.from_defaults(persist_dir='./storage')
            # load index
            index = load_index_from_storage(storage_context, service_context=service_context)
        else:
            # 这步会解析documents目录下的文件。 把文件放在documents目录下(支持txt,md,docx,pdf..)
            documents = SimpleDirectoryReader('documents').load_data()
            # 这里会把解析后的文本内容,到openai获取embeddings数据(需要访问openai)
            index = GPTVectorStoreIndex.from_documents(documents, service_context=service_context)
            # 解析文件后的数据存储到 storage目录下, 下次就不要再去解析
            index.storage_context.persist()
    
        # 开始查询
        query_engine = index.as_query_engine()
        # (需要访问openai)
        res = query_engine.query("<svn有问题需要找谁?>")
        print(res)
        #回复是:  
        # svn有问题需要找artifactory/svn运维人员xxx2
  • 整个代码最终目标是产生prompt

    Context information is below.
    ---------------------
    运维过程常用联系人
    
    gitee/gitlab运维:  xxx1
    
    artifactory/svn运维:  xxx2
    ---------------------
    Given the context information and not prior knowledge, answer the question: <svn有问题需要找谁?>
  • 答复

    svn有问题需要找artifactory/svn运维人员xxx1

总结来说: 通过openai的embedding将文本转化成向量 ,然后存入向量数据库, 然后通过向量相关性来找出相关的高文档片段作为上下文, 加上问题一起发送给大模型,获得最终结果

整个流程核心点:

  • openai的embedding接口
  • 向量数据库求top-n

引入向量数据库的必要性

  • 再回到全文索引的关键字搜索的两个问题

关键词绝对匹配

关键词比较短的情况,搜索结果会特别大

举个例子我们搜索elk相关问题时, 如果我们搜索的问题中包含logstash, 假设你的文档里不包含logstash这个关键词,但包含elk这个词时。 那么关键字搜索时搜不到相关的文章。 此时如果用借助向量数据库, logstash 与 elk 这两个词在openai-embedding模型里是必然有相关性的,那么它就能把相关连的文档搜出来, 然后再借助大模型的语言组织能力给你一个跟文档相关的答案。 引入了向量数据库,关键词绝对匹配的问题就不存在了。

由于大模型有理解能力, 那么你在搜索问题时,其实像和人类一样问题就变的自然了,完整表达自己的问题就好了。

  • 当然引入向量库主要的原因是token限制。 如果未来大模型没有token限制, 向量数据库在这个流程里就没有存在必要。

开源模型支持

还有一个问题时数据泄密问题。 这个llamda-index其实是支持开源的模型的。 整个流程里与openai有交互的有两个

  1. embedding 求文本的向量
  2. 给大模型问题, 让大模型给出答复

对应的解决办法

  1. 使用Langchain的的embedding模型
  2. LLMPredictor 可以换成 HuggingFaceLLMPredictor

还需要解决的问题

通过上面的小demo, 我们能初步实现大模型和本地知识库的连接

当然还有很多其他的问题

  • 日常文档里,其实有很多截图类的东西

    这个目前的话,llmada-index目前在解析文档时会把图片,链接去掉 , 那么其实求相关还是问题和文档文本的相关性。 图片信息内容就丢失了

  • 当问题得到回复时,我们还是想看完整文档, 这个需要对文档做个关联索引

  • 如果你的业务足够垂直的话,其实openai的embedding也是不够好的。那么关联性就不够好.

    这块可能需要找领域相关的embedding模型来替代

  • 怎么将业务的知识库和问答系统中间的流程自动化

    知识库收集标准

    知识库收集后的embedding和建立文档索引

...
2019-2024 zs1621