大模型之所以强大,在于其识识别能力、上下文理解能力,以及内容生成能力,打开了通用人工智能的大门。
垂域模型发展之路
大型语言模型(llm)是指能够生成与人类语言非常相似的文本并以自然方式理解提示的机器学习模型。这些模型使用广泛的数据集进行训练,这些数据集包括书籍、文章、网站和其他来源。通过分析数据中的统计模式,LLM可以预测给定输入后最可能出现的单词或短语。
对于AIGC这个赛道来说,算力、算法、数据都是促使它优化的主要因素,而GPT技术的迭代升级,将大数据的重要性放到了一个空前的位置。在大算力、大投资、大规模的要求下,后来的AIGC企业想要做出更好的技术,只会变得更难。
另一种声音则认为垂类模型必然存在,也是具体落地到业务场景尤其是ToB业务场景时,必然的选择。 社区不断放出来的DB-GPT、CodeGPT、LawGPT、FinGPT等项目。
目前的LLM的一个全景图
还有第三种声音:融合。 我们最近在DB-GPT项目的开发、测试、验证过程中,体会到了BaseModel的重要性。 在DB-GPT项目中,我们是在基于开源的大模型,培养一个数据库领域专家。 在这个过程中,我们也尝试了众多模型,深刻的领悟到了什么是"教不会的笨学生"。 同样的知识体系,同样的教学手段,这教出来的差距咋这么大呢?
垂域的挑战
广泛的应用场景使得它在重塑企业工作流程,实现部分工作流程自动化、自助化,优化企业组织结构,提高企业资源分配的灵活性和合理性等方面发挥重要作用,通俗的讲就是:提升生产效率,降低生产成本。
目前很多企业希望将ChatGPT的能力应用到企业内部当中,但ChatGPT是个预训练模型,其所能回答的知识主要来源于互联网上公开的通用知识库,对于部分垂直领域和企业内部的私有知识库的问答无法起到很好的效果,因此,针对这类场景,企业可以基于OpenAI提供的模型服务以及相关生态工具(比如langchain、huggingFace等),构建企业自己特有的知识库问答系统,并在内部知识库问答系统之上,再搭建客服问答系统以及其他的企业助手工具。
相较与通用模型,垂域模型在合规、数据、算力、工程、算法方面遇到的挑战更大。 为何如此说呢?通用模型发展到今天,基本可以定义为巨头们的生意。 而巨头们在数据、算力、工程、算法等方面都有很深的积累。 而通用大模型的训练数据,一般都是互联网公开的数据,所以在合规方面的挑战也不像垂域大模型。
在垂直领域,算力、工程包括算法,主要需要解决的是成本问题。 毕竟如若一个垂域模型需要大几百万的部署推理成本,那也很难有落地的可行性。
ChatGPT现在的问题在于,他给出的答案往往是大众性质的、普适化的,而非个性化的。
在用户刚开始做检索的时候,大部分情况下对自己的需求是没有很明确的认知的。而在使用传统浏览器的时候,往往是在检索过程中才能进一步缩小自己的需求范围,而ChatGPT是直接将用户能看到的答案范围进行了缩减,它给出的答案是正确的,但不一定就是最合适用户的。
另一方面合规与数据是制约垂域模型发展最重要的因素。 垂域的数据是非常重要的资产,所以收集数据做Training的复杂度巨高。 单一企业或者组织的数据,受限与数据规模与质量,很难独立完成训练。 所以数据流通、数据价值交换与确权的诉求,会随着垂域模型的发展越来也大。 像隐私计算、区块链这样的技术,需要面对大模型时代的需求,继续做更多深入场景与领域的探索。 面向未来,区块链、隐私这些技术,更好的定位可能是服务与AI。
垂直领域或者说纵深领域,一般都是建立在通识知识之上的。比如 你要具备很好的算法、编程、系统等等各方面的知识才能够学习这个专业纵深领域,否则基本的通识知识跟原理都不懂,普通的代码结构与逻辑都理不顺,又如何在这个领域有所深度呢?就好比说一个学生如果连本科阶段的知识都没有学,就直接跨入到研究生阶段,那必然学起来很吃力,是很难学会的。如果说有一种手段,可以跳过本科教育培养的理解力,直接学习研究生的课程,那也多半是靠死记硬背。
以上是技术层面的, 那么在大模型落地过程中,还有哪些其他层面的问题呢? 我们不妨在回顾一下大模型发展的几个重要的因素。合规、数据、算力、工程、算法。 这里我把合规跟数据放在了最前面。 为什么呢? 大家都知道LLM目前主要是GPT,其生成内容与算法内核不具备明确的解释性,面对范互联网或者数据敏感性相对较低的ToC领域,可以具备一定的落地能力了,我们也看到GPT-4出现之后,大量的ToC的落地场景与应用,有些应用也确实很让人惊喜。 但数据敏感性较高的ToB呢? 尤其数据作为新的生产资料,是一个企业、一个国家核心资产的今天。 ToB的业务还能用通用大模型吗?
添加图片注释,不超过 140 字(可选)
答案肯定是不能的, 无论你模型能力是否够强,都是不能的。因为数据就是一个企业的命脉,是一个行业的命脉,更是一个国家的命脉。试想一下,你会把自己的命脉拱手交给别人吗? 总不能把?
所以说,垂域LLM必然是存在的,且会长在通用LLM之上,即将垂域知识融入到一个相对智能的通用LLM之上,打造行业/领域的专有模型,并进行私有化部署,是ToB业务未来非常重要的一条发展路径。
整体流程:
目前的开源知识库问答系统有很多,他们的系统架构都大同小异,基本流程是:
1、领域知识向量化:将垂直行业领域的知识库文档进行Embedding向量化处理,并将处理后的语义向量Vectors存入向量数据库Vector Database中(这个步骤中还包括对非结构化数据先转化成文本数据,并对长文本进行Splitter分割处理)。
2、用户问题向量化:将用户的问题进行向量化Embedding处理,转化为Vector search
3、得到TopN条匹配知识:将用户问题Vector search 和向量数据库进行查询匹配,返回相似度最高的TopN条知识文本
4、构建Prompt,调用OpenAI API:将匹配出的文本和用户的问题上下文一起提交给 LLM,根据Prompt生成最终的回答
添加图片注释,不超过 140 字(可选)
架构介绍说明
一般框架如:github上热度较高的是quivr,privateGPT等。
这里提供一个参考:
1、Embeddgings model选择 要将领域知识向量化,需要有Embeddings model,最简单的方案是使用OpenAI的Embeddings API。 由于OpenAI的Embeddings model是通用模型,对垂直行业并不是最适合的,会出现回答不准确的情况。如果数据量较大,需要反复调用Embeddgins API,效率较低、成本较高。 可以考虑自己基于知识库自训练或基于一些现成的模型,HuggingFace上有很多Embeddings model可供参考使用。
2、向量数据库选择 向量数据库在相似文本搜索、个性化推荐、相似图片搜索等都有很好的应用场景。开源的向量数据库有qdrant,weaviate,milvus,elasticsearch等,推荐qdrant。
3、LLM框架 LangChain及LlamaIndex (原GPT Index) 这样的LLM框架,封装了很多LLM的工具,可以极大程度提升与LLM的集成效率。 LlamaIndex (原GPT Index) 入门门槛更低,入门文档也写得比较详尽。LangChain更为强大灵活,qdrant对LangChain的集成更好。
第一部分:
利用LLaMA 7b和Langchain从头开始创建自己的Document Assistant
在本文中,我将演示如何利用LLaMA 7b和Langchain从头开始创建自己的Document Assistant。
背景知识
1、LangChain 🔗 LangChain是一个令人印象深刻且免费的框架,它彻底改变了广泛应用的开发过程,包括聊天机器人、生成式问答(GQA)和摘要。通过将来自多个模块的组件无缝链接,LangChain能够使用大部分的llm来创建应用程序。 2、LLaMA 2023年2月24日,Meta向公众发布了LLaMA模型,,拥有70亿到650亿个参数的模型集合,是当时最全面的语言模型之一。
添加图片注释,不超过 140 字(可选)
3、什么是GGML GGML是一个用于机器学习的张量库,它只是一个c++库,允许你在CPU或CPU + GPU上运行llm。它定义了用于分发大型语言模型(llm)的二进制格式。GGML使用了一种称为量化的技术,该技术允许大型语言模型在消费者硬件上运行。 4、量化 模型的权重是浮点数。就像表示大整数(例如1000)比表示小整数(例如1)需要更多的空间一样,表示高精度浮点数(例如0.0001)比表示低精度浮点数(例如0.1)需要更多的空间。量化大型语言模型的过程涉及降低表示权重的精度,以减少使用模型所需的资源。GGML支持许多不同的量化策略(例如4位、5位和8位量化),每种策略在效率和性能之间提供不同的权衡。 下面是量化后模型大小的对比:
添加图片注释,不超过 140 字(可选)
5、Streamlit🔥 Streamlit 是一个用于构建数据科学和机器学习应用程序的开源 Python 库。它旨在使开发人员能够以简单快速的方式构建交互式应用程序,无需繁琐的前端开发。Streamlit 提供了一组简单的 API,可用于创建具有数据探索、可视化和交互功能的应用程序。只需要通过简单的 Python 脚本就可以创建一个 Web 应用程序。可以利用 Streamlit 的丰富组件库来构建用户界面,例如文本框、滑块、下拉菜单和按钮,以及可视化组件,例如图表和地图。
构建方式
1、建立虚拟环境和项目结构 设置虚拟环境为运行应用程序提供了一个受控和隔离的环境,确保其依赖关系与其他系统范围的包分离。这种方法简化了依赖关系的管理,并有助于维护不同环境之间的一致性。 然后就是创建我们的项目,一个好的结构会加速我们的开发,如下图所示
添加图片注释,不超过 140 字(可选)
在models的文件夹中,我们要存储下载的llm,setup_env.bat将从pipfile中安装所有依赖项。而run_app.bat则是直接运行我们的app。(以上2个文件都是windows环境下的脚本) 2、在本地机器上安装LLaMA 为了有效地使用模型,必须考虑内存和磁盘。由于模型需要完全加载到内存中,因此不仅需要有足够的磁盘空间来存储它们,还需要足够的RAM在执行期间加载它们。比如65B模型,即使在量化之后,也需要40gb的RAM。 所以为了在本地运行,我们将使用最小版本的LLaMA,也就是LLaMA 7B。虽然它是最小的版本,但是LLaMA 7B也提供了很好的语言处理能力,我们能够高效地实现预期的结果。 为了在本地CPU上执行LLM,我们使用GGML格式的本地模型。这里直接从Hugging Face Models存储库直接下载bin文件,然后将文件移动到根目录下的models目录中。 上面我们已经是说了,GGML是c++库,所以还需要使用Python调用C++的接口,好在这一步很简单,我们将使用llama-cpp-python,这是LLaMA .cpp的Python绑定,它在纯C/ c++中充当LLaMA模型的推理。cpp的主要目标是使用4位整数量化来运行LLaMA模型。这样可以可以有效地利用LLaMA模型,充分利用C/ c++的速度优势和4位整数量化🚀的优势。 llama.cpp还支持很多其他模型,下图是列表:
添加图片注释,不超过 140 字(可选)
准备好GGML模型和所有依赖项之后,就可以开始LangChain进行集成了。但是在开始之前,我们还需要做一下测试,保证我们的LLaMA在本地使可用的:
添加图片注释,不超过 140 字(可选)
看样子没有任何问题,并且程序是完全脱机并以完全随机的方式(可以使用温度超参数)运行的。 3、LangChain集成LLM 现在我们可以利用LangChain框架来开发使用llm的应用程序。 为了提供与llm的无缝交互,LangChain提供了几个类和函数,可以使用提示模板轻松构建和使用提示。它包含一个文本字符串模板,可以接受来自最终用户的一组参数并生成提示符。让我们先看几个例子。 没有输入参数的模板
添加图片注释,不超过 140 字(可选)
多个参数的模板
添加图片注释,不超过 140 字(可选)
下面我们可以使用LangChain进行集成了
添加图片注释,不超过 140 字(可选)
目前我们使用了单独的组件,通过提示模板对其进行格式化,然后使用llm,在llm中传递这些参数以生成答案。对于简单的应用程序,单独使用LLM是可以的,但是更复杂的应用程序需要将LLM链接起来——要么相互链接,要么与其他组件链接。 LangChain为这种链接🔗应用程序提供了Chain接口。我们可以将Chain定义为对组件的调用序列,其中可以包含其他Chain。Chain允许我们将多个组件组合在一起,以创建一个单一的、一致的应用程序。例如,可以创建一个Chain,它接受用户输入,使用Prompt Template对其进行格式化,然后将格式化后的响应传递给LLM。我们可以通过将多个Chain组合在一起,或者与其他组件组合在一起,来构建更复杂的Chain。这其实就和我们一般数据处理中的pipeline是类似的。 创建一个非常简单的Chain🔗,它将接受用户输入,用它格式化提示符,然后使用我们已经创建的上述各个组件将其发送到LLM。
添加图片注释,不超过 140 字(可选)
4、生成嵌入和向量库 在许多LLM应用程序中,需要特定于用户的数据,这些数据不包括在模型的训练集中。LangChain提供了加载、转换、存储和查询数据的基本组件,我们这里可以直接使用
添加图片注释,不超过 140 字(可选)
上图包含5个组件:
-
文档加载器:它用于将数据加载为文档。
-
文档转换器:它将文档分成更小的块。
-
嵌入:它将块转换为向量表示,即嵌入。
-
嵌入向量存储:用于将上述块向量存储在矢量数据库中。
-
检索器:它用于检索一组向量,这些向量以嵌入在相同Latent空间中的向量的形式与查询最相似。
我们将实现这五个步骤,流程图如所提供的下图所示。
添加图片注释,不超过 140 字(可选)
我们这里使用维基百科上复制的一段关于一些DC超级英雄的文本作为开发测试使用。原文如下:
添加图片注释,不超过 140 字(可选)
a.加载和转换文档
使用文本加载器创建一个文档对象(Lang chain提供了对多个文档的支持,可以根据文档使用不同的加载器),使用load方法检索数据,并将其作为文档从预配置的源加载。 加载文档之后,通过将其分解为更小的块来继续转换过程。使用TextSplitter(默认情况下,拆分器以' \n\n '分隔符分隔文档)。如果将分隔符设置为null并定义特定的块大小,则每个块将具有指定的长度。这样就得到了列表长度将等于文档的长度除以块大小的一个块列表。
添加图片注释,不超过 140 字(可选)
b.Embeddings
词嵌入只是一个词的向量表示,向量包含实数。词嵌入通过在低维向量空间中提供词的密集表示来解决简单的二进制单词向量由于维数高的问题。 LangChain中的基Embeddings类公开了两个方法:一个用于嵌入文档,另一个用于嵌入查询。前者接受多个文本作为输入,后者接受单个文本作为输入。 因为后面的检索也是检索嵌入在相同潜在空间中最相似的向量,所以词向量必须使用相同的方法(模型)生成。
添加图片注释,不超过 140 字(可选)
c.创建存储和检索文档
矢量存储有效地管理嵌入数据的存储,并加速矢量搜索操作。我们将使用Chroma,一个专门用于简化包含嵌入的人工智能应用程序的开发的矢量数据库。它提供了一套全面的内置工具和函数,我们只需要使用 pip install chromadb 命令将它安装在本地。
添加图片注释,不超过 140 字(可选)
现在我们可以存储和检索向量了,下面就是与LLM来整合了。
添加图片注释,不超过 140 字(可选)
到这一步,已经可以使用本地运行的LLM构建问答机器人了,这个结果还不错,但是我们还有更好的要求,就是一个GUI界面。 5、Streamlit 如果你只喜欢命令行的方式运行,则这一节是完全可选的。因为在这里我们将创建一个允许用户上传任何文本文档的WEB程序。可以通过文本输入提出问题,来对文档进行分析。
import streamlit as st from langchain.llms import LlamaCpp from langchain.embeddings import LlamaCppEmbeddings from langchain.prompts import PromptTemplate from langchain.chains import LLMChain from langchain.document_loaders import TextLoader from langchain.text_splitter import CharacterTextSplitter from langchain.vectorstores import Chroma # Customize the layout st.set_page_config(page_title="DOCAI", page_icon="🤖", layout="wide", ) st.markdown(f""" <style> .stApp {{background-image: url("https://images.unsplash.com/photo-1509537257950-20f875b03669?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1469&q=80"); background-attachment: fixed; background-size: cover}} </style> """, unsafe_allow_html=True) # function for writing uploaded file in temp def write_text_file(content, file_path): try: with open(file_path, 'w') as file: file.write(content) return True except Exception as e: print(f"Error occurred while writing the file: {e}") return False # set prompt template prompt_template = """Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. {context} Question: {question} Answer:""" prompt = PromptTemplate(template=prompt_template, input_variables=["context", "question"]) # initialize hte LLM & Embeddings llm = LlamaCpp(model_path="./models/llama-7b.ggmlv3.q4_0.bin") embeddings = LlamaCppEmbeddings(model_path="models/llama-7b.ggmlv3.q4_0.bin") llm_chain = LLMChain(llm=llm, prompt=prompt) st.title("📄 Document Conversation 🤖") uploaded_file = st.file_uploader("Upload an article", type="txt") if uploaded_file is not None: content = uploaded_file.read().decode('utf-8') # st.write(content) file_path = "temp/file.txt" write_text_file(content, file_path) loader = TextLoader(file_path) docs = loader.load() text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=0) texts = text_splitter.split_documents(docs) db = Chroma.from_documents(texts, embeddings) st.success("File Loaded Successfully!!") # Query through LLM question = st.text_input("Ask something from the file", placeholder="Find something similar to: ....this.... in the text?", disabled=not uploaded_file,) if question: similar_doc = db.similarity_search(question, k=1) context = similar_doc[0].page_content query_llm = LLMChain(llm=llm, prompt=prompt) response = query_llm.run({"context": context, "question": question}) st.write(response)
界面图
这样一个简单的并且可以使用的程序就完成了。
小结
通过LangChain和Streamlit我们可以方便的整合任何的LLM模型,并且通过GGML我们可以将大模型运行在消费级的硬件中,这对我们个人研究来说使非常有帮助的。
第二部分:
DB-GPT垂域模型应用实践
以Text2SQL这个场景来介绍应用实践。 具体的任务如下:
有一个BI分析的任务,需要关联6张表来进行数据分析,当前的数据库中有1000+表。
当前LLM处理这个任务时,有两个大的难点。
1. LLM当前不具备6张表关联如此复杂的SQL编写能力。
2. 受限与Token长度,我们无法直接将所有的表信息提供给模型来生成正确的SQL语句。 基于大模型当前的能力,我们通过系统架构优化的方式,对此问题进行了解决, 首先我们看看整体的架构图。
添加图片注释,不超过 140 字(可选)
这里我们用到了几个比较关键的技术思路。
1. Summary + Embedding 2. 大帮小 3. CoT+ToT(复杂任务拆步解)
Summary + Embedding
Summary + Embedding这一步相信大家已经比较熟悉了, 如果有不了解的可以看一下之前我发的一篇简单介绍实战的文章。
Summary+Embedding 这一步实际就是对元数据进行向量化,以供后续大模型使用。那为什么要进行Summary呢? 直接查询元数据丢给大模型行不行? 实践证明是不行的, 在实际用户使用过程中,一张用户详情表,会命名为udtail, 这你让大模型怎么认嘛? 命名的人你自己认不认得到吗? 在实际落地中有大量诸如的问题,所以我们要对元数据进行Summary,其目的是让模型知道udtail这个命名是用户详情表。 除此之外,生产环境一般会有数百上千万的表,将这些表一股脑都丢给大模型,显然是不现实,也不可能。 所以我们要做Embedding。在DB-GPT中,我们也设计了第一个简易版本的Summary脚手架。代码如下:
class DBSummary: def __init__(self, name): self.name = name self.summery = None self.tables = [] self.metadata = str def get_summery(self): return self.summery class TableSummary: def __init__(self, name): self.name = name self.summery = None self.fields = [] self.indexes = [] class FieldSummary: def __init__(self, name): self.name = name self.summery = None self.data_type = None class IndexSummary: def __init__(self, name): self.name = name self.summery = None self.bind_fields = []
通过对库、表、字段、索引进行简要的Summary,我们即可做到让大模型理解我们的元数据,理解我们的业务语义。
大帮小
大模型指的是AIGC通用大模型,体量超大;小模型指的是垂域的大模型,体量也大,但相比小一点。
再说到大帮小, 大帮小其实指的是大模型帮小模型,更具体一点。就是通过ChatGPT/GPT-4、通义千文,文心一言这样更大的模型,来辅助私有化部署的百亿级模型来完成任务。 在我们写SQL这个案例当中,一个关联6张表的查询小模型是非常难理解的,因此我们会根据Query + Summary的内容让大模型先完成语义提取。 将复杂问题的理解,格式化输出一个固定的ToT的模版内容,将复杂的任务拆解为几个独立的简单步骤。
在此之后,我们将每个小步的任务丢给小模型去处理。 当然在这个环节,我们为了更稳定的效果,还需要跟大模型完成一些交互。 比如在DB-GPT当中,我们发现Vicuna-13b在格式化输出Json时,准确率跟稳定性都比较差,正确率不到70%,这需要我们编写大量的代码来处理格式。 以如下格式为例,但当我们调用GPT-4来格式化时,准确率跟稳定性能达到95%以上。
RESPONSE_FORMAT = { "thoughts": { "reasoning": "reasoning", "speak": "thoughts summary to say to user", }, "sql": "SQL Query to run", }
因为是一个多步拆分任务,所以模型执行的中间结果,我们会暂存在一个中间态。 最后在通过链式计算来返回最终正确的结果。
CoT/ToT
添加图片注释,不超过 140 字(可选)
思维链以及思维树,已经是业界非常流行的方案了。 尤其在插件使用上,思维链模型应用非常广泛,其中Auto-GPT整个推理过程就大量使用了思维链进行反复推理,来生成最终正确的结果。 同样在我们的方案中,也不例外。 但不同的是,在私有化模型下,反复推理的成本跟模型稳定性,目前表现还不那么令人满意,为了节约成本增加稳定性,我们在ToT环节里面,加入了ChatGPT/GPT-4来做正确性论证的能力。
添加图片注释,不超过 140 字(可选)
以上即为我们综合考虑成本、隐私、效果制定的一个折中方案。 核心数据资产通过本地化Embedding模型,Summary之后存储在私有向量数据中。 用户复杂的问题通过DB-GPT Proxy转接给中心化大模型做语义识别与任务拆解。 拆解完成的小任务,通过DB-GPT中的私有化大模型完成具体的任务执行。 最后结果通过思维链/思维树的路径进行多轮验证来确保得到准确的结果。 在这个过程中,用户数据与跟用户环境交互的模型都是本地化的。但是在任务拆解、格式化输出等方面,我们为了提供准确率同时降低推理成本,将这部分任务拆解给了ChatGPT/GPT-4这样的API来完成。
第三部分:
基于Azure OpenAI模型服务的知识库问答系统
Q&A with Semantic Answering with Azure OpenAl Service
这个demo搭建了一个简单的基于OpenAI的知识库问答系统,企业可以将内部的各类文档、表格、图片等转化为方便模型计算的语义向量,存入向量数据库中。当用户提出问题时,它从知识库(向量库)中检索匹配出最相关的文档,然后使用GPT来生成问题的最终答案。
企业可以基于这个demo以及自身的业务场景需求做修改,如果是只是想搭建一个文档检索工具,那么对投入知识库的各类数据源文档格式可以不做过多的要求,直接上传便可。如果是想搭建一个问答系统甚至客服系统,那么就需要对数据源文档的内容格式进行重构,尽可能将非结构化数据转化成文本数据,最好做成Q&A问答对的形式有利于提升模型的问答质量。
上述demo,之所以是基于Azure OpenAI,而不是OpenAI的模型接口做开发,主要是考虑合规性和企业数据保密性等问题,毕竟谁也不希望像手机厂商某星那样,企业机密数据被OpenAI模型用于自身训练,导致数据泄露对吧,而且Azure OpenAI不需要梯子,毕竟微软提供的企业级解决方案,稳定性、可靠性等方面会更高一些。
这个demo也是提供了多种部署方式,如果是初次部署体验,可以采用readme.md中提到的这种docker方式快速启动:Run everything locally in Docker (WebApp + Redis Stack + Batch Processing),如果后面想要修改测试,可以使用其他本地部署的方式,不过本地部署需要注意部署环境,会踩一些坑,不过问题不大。
demo中运用了多个Azure云服务组件,这些都是可替代的,比如目前demo是使用Azure Form Recognizer表单识别器去做文档识别,如果希望支持更多的数据源文档可识别类型,可参考另一个demo:quivr,提供的更丰富的数据源类型,主要是基于langchain的工具包做识别,其中还支持音频和视频识别。 向量数据库Vector Database除了用Redis之外,也可以用其他的比如Chroma、Pinecone等,langchain也提供了向量存储工具包。 而核心组件Embedding向量化工具目前用的是Azure OpenAI Embedding模型,虽然他不是目前最强的,但针对中文识别这一块,其识别准确率还是较高的,如果是考虑到调用远程API接口,涉及延迟、数据安全性等问题,也可以采用其他本地模型来完成Embedding,比如:Sentence Embeddings text2vec-base-chinese。至于最后一个步骤,匹配到知识库中的相关文档答案后,要生成最终的回答内容,可以根据企业自身的场景选择用GPT-3.5或者GPT-4,也可以是GPT-davinci(仅限特定场景效果较好,性价比没有GPT-3.5高)
此外,基于知识库问答系统之上,可以做各种Prompt Engineering,搭建客服系统,也可以集成其他插件,实现更多样的场景应用,比如:
集成第三方插件包,实现自动生成SQL语句,生成Python代码,并执行语句,将返回的结果生成表格,生成统计分析图等。
集成联网工具,当知识库无法匹配到问题的答案时,GPT可以主动联网,获取最新的互联网数据。
集成邮件API,实现邮件群发,邮箱整理分析统计等。
基于langchain的动态代理功能,可以实现让GPT处理更复杂的任务,比如将一个复杂的任务拆解成N个步骤,针对各个步骤,GPT会自主判断调用哪个工具去解决对应的问题,例如先调用联网工具,再调用计算器,接着调用内容生产模型,最后调用邮件助手,将整理的最终结果发送到指定邮箱。
结语
当然以上并不是唯一的、或者完美的方案,我们也在不断的探索大模型私有化落地的各种可能。
垂域大模型的发展也势必会随着业务与时代的诉求,逐步加速。saas公司也将会得到很大的发展很影响。
面对垂域模型发展过程中的挑战,需要做更多的基础设施建设,打通垂域模型发展之路,才能更好助力业务落地。这方面腾讯已经发布了行业大模型的发展思路,算是开了个好头,后续期望更多的企业也能够参与共建基础设施。
如果对langchain感兴趣,有更专业的文章参考:https://zhuanlan.zhihu.com/p/640936557