当前位置:   article > 正文

LLM实战 | 基于本地知识库打造属于自己的New Bing!_nlp_bert_document-segmentation_chinese-base

nlp_bert_document-segmentation_chinese-base

ChatGPT狂飙160天,世界已经不是之前的样子。

新建了人工智能中文站https://ai.weoknow.com
每天给大家更新可用的国内可用chatGPT资源


今天分享下如何利用开源LLM大语言基座模型来管理自己本地的知识库,比如你电脑里的paper/学习资料等,打造属于自己的NewBing。

前言

ChatGPT等LLM大模型的知识延迟问题和幻想问题一直是两个非常难以解决的问题。而其背后的技术选型导致了这两个问题必然会存在。

  • 知识延迟:由于大模型的知识来自于训练时喂给它的训练数据,且大模型很难做到实时更新,一般更新一次也得花上好几个月,所有它能接收到的数据必然是延迟的。

  • 幻想问题:由于LLM采用的概率模型,即预测生成下一个字符概率是多少,所有或多或少的它在生成结果的时候都有定的可能出现错误。

那么如何解决这两个问题呢?目前比较好的方式就是利用大模型极强的语义理解能力,给大模型外挂一个知识库或者搜索引擎去解决这两个问题。如今的new_bing chat 则是采用这种技术路线,下图就是我问new_bing关于如何解决LLM知识延迟和幻想问题的相关截图:

img

它的整个流程应该是:

  • 1.利用bing去搜索和用户输入相关的文本。

  • 2.采用合适的prompt + 上述步骤搜索到的文本 + 用户输入 ,一并输入给chatgpt

    我猜是prompt是:利用上述资料回复用户问题(当然不可能这么简单)。

  • 3.利用chatgpt的语义理解能力和内容总结能力生成的结果 。

其实解决大模型知识延迟和幻想的问题在我问newbing搜索结果的第二条给出了和上述流程比较契合的回答:

使用更丰富和多样的数据源,例如结构化或半结构化的数据、知识图谱、多模态数据等,以增加模型的知识覆盖率和质量,提高模型的泛化能力和准确性。

而今天笔者就介绍一下如何利用非结构化的文本知识库去减轻LLM的幻想问题。

基于知识库 + LLM的知识问答系统的流程和架构

具体的流程和上述new_bing chat的流程很像,但是多了一个步骤

1.将知识库的文本分块,并进行向量化;

2.用户的query向量化,并在知识库中进行检索,返回最相关的TOPN的文本块;

3.采用合适的prompt + 上述步骤搜索到的文本 一并输入给LLM;

4.利用LLM的语义理解能力和知识问答能力,生成问题的答案。

下图则是最近github上很火的一个基于chatGLM实现的一个基于知识库的问答系统的架构图:

https://github.com/imClumsyPanda/langchain-ChatGLM

原理图

基于知识库 + LLM的知识问答系统实战

本项目地址:https://github.com/wp931120/LongChainKBQA/tree/main其中,

  • 1.文本分块模块:采用的是阿里开源nlp_bert_document-segmentation_chinese-base 语义分割模型对文本进行拆分;

  • 2.文本向量化模块:采用的是text2vec-large-chinese 模型对文本向量化;

  • 3.LLM模块:采用的是ChatYuan-large-v2 大语言模型;

  • 4.整合模块:langchain可将上述模块轻松的进行整合,构建知识问答LLM。

1.文本分块和向量化模块

具体技细节就是利用nlp_bert_document-segmentation_chinese-base模型将文本分割后,利用text2vec-large-chinese向量化,最终构建一个faiss索引,并持久化。

  1. from langchain.document_loaders import UnstructuredFileLoader, TextLoader, DirectoryLoader
  2. from langchain.embeddings.huggingface import HuggingFaceEmbeddings
  3. from langchain.vectorstores import FAISS
  4. from config import Config
  5. from utils.AliTextSplitter import AliTextSplitter
  6. class DocumentService(object):
  7.     def __init__(self):
  8.         self.config = Config.vector_store_path
  9.         self.embeddings = HuggingFaceEmbeddings(model_name=Config.embedding_model_name)
  10.         self.docs_path = Config.docs_path
  11.         self.vector_store_path = Config.vector_store_path
  12.         self.vector_store = None
  13.     def init_source_vector(self):
  14.         """
  15.         初始化本地知识库向量
  16.         :return:
  17.         """
  18.         loader = DirectoryLoader(self.docs_path, glob="**/*.txt", loader_cls=TextLoader)
  19.         # 读取文本文件
  20.         documents = loader.load()
  21.         text_splitter = AliTextSplitter()
  22.         # 使用阿里的分段模型对文本进行分段
  23.         split_text = text_splitter.split_documents(documents)
  24.         # 采用embeding模型对文本进行向量化
  25.         self.vector_store = FAISS.from_documents(split_text, self.embeddings)
  26.         # 把结果存到faiss索引里面
  27.         self.vector_store.save_local(self.vector_store_path)
  28.     def load_vector_store(self):
  29.         self.vector_store = FAISS.load_local(self.vector_store_path, self.embeddings)
  30. if __name__ == '__main__':
  31.     s = DocumentService()
  32.     ###将文本分块向量化存储起来
  33.     s.init_source_vector()

2.LLM模块

加载ChatYuan-large-v2 大语言模型,当然也可以选择ChatGLM或者Moss等。

  1. from typing import List, Optional
  2. from langchain.llms.base import LLM
  3. from langchain.llms.utils import enforce_stop_tokens
  4. from transformers import AutoModel, AutoTokenizer
  5. from config import Config
  6. class LLMService(LLM):
  7.     max_token: int = 10000
  8.     temperature: float = 0.1
  9.     top_p = 0.9
  10.     history = []
  11.     tokenizer: object = None
  12.     model: object = None
  13.     def __init__(self):
  14.         super().__init__()
  15.     @property
  16.     def _llm_type(self) -> str:
  17.         return "LLM"
  18.     def _call(self,
  19.               prompt: str,
  20.               stopOptional[List[str]] = None) -> str:
  21.         response, _ = self.model.chat(
  22.             self.tokenizer,
  23.             prompt,
  24.             history=self.history,
  25.             max_length=self.max_token,
  26.             temperature=self.temperature,
  27.         )
  28.         if stop is not None:
  29.             response = enforce_stop_tokens(response, stop)
  30.         self.history = self.history + [[None, response]]
  31.         return response
  32.     def load_model(self, model_name_or_path: str = "ClueAI/ChatYuan-large-v2"):
  33.         """
  34.         加载大模型LLM
  35.         :return:
  36.         """
  37.         self.tokenizer = AutoTokenizer.from_pretrained(
  38.             Config.llm_model_name,
  39.             trust_remote_code=True
  40.         )
  41.         self.model = AutoModel.from_pretrained(model_name_or_path, trust_remote_code=True)
  42.         self.model = self.model.eval()
  43. if __name__ == '__main__':
  44.     chatLLM = LLMService()
  45.     chatLLM.load_model()

3.知识问答模块

  1. from langchain.chains import RetrievalQA
  2. from langchain.prompts.prompt import PromptTemplate
  3. from config import Config
  4. from document import DocumentService
  5. from llm import LLMService
  6. class LangChainApplication(object):
  7.     def __init__(self):
  8.         self.config = Config
  9.         self.llm_service = LLMService()
  10.         ###加载llm和知识库向量
  11.         print("load llm model ")
  12.         self.llm_service.load_model(model_name_or_path=self.config.llm_model_name)
  13.         self.doc_service = DocumentService()
  14.         print("load documents")
  15.         self.doc_service.load_vector_store()
  16.     def get_knowledge_based_answer(self, query,
  17.                                    history_len=5,
  18.                                    temperature=0.1,
  19.                                    top_p=0.9,
  20.                                    top_k=1,
  21.                                    chat_history=[]):
  22.         #定义prompt
  23.         prompt_template = """基于以下已知信息,简洁和专业的来回答用户的问题。
  24.                                         如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息",不允许在答案中添加编造成分,答案请使用中文。
  25.                                         已知内容:
  26.                                         {context}
  27.                                         问题:
  28.                                         {question}"""
  29.         prompt = PromptTemplate(template=prompt_template,
  30.                                 input_variables=["context""question"])
  31.         self.llm_service.history = chat_history[-history_len:] if history_len > 0 else []
  32.         self.llm_service.temperature = temperature
  33.         self.llm_service.top_p = top_p
  34.         # 声明一个知识库问答llm,传入之前初始化好的llm和向量知识搜索服务
  35.         knowledge_chain = RetrievalQA.from_llm(
  36.             llm=self.llm_service,
  37.             retriever=self.doc_service.vector_store.as_retriever(
  38.                 search_kwargs={"k"top_k}),
  39.             prompt=prompt)
  40.         knowledge_chain.combine_documents_chain.document_prompt = PromptTemplate(
  41.             input_variables=["page_content"], template="{page_content}")
  42.         knowledge_chain.return_source_documents = True
  43.         ### 基于知识库的问答
  44.         result = knowledge_chain({"query": query})
  45.         return result
  46.     def get_llm_answer(self, query=''):
  47.         prompt_template = """请回答下列问题:
  48.                             {}""".format(query)
  49.         ### 基于大模型的问答
  50.         result = self.llm_service._call(prompt_template)
  51.         return result
  52. if __name__ == '__main__':
  53.     application = LangChainApplication()
  54.     print("大模型自己回答的结果")
  55.     result = application.get_llm_answer('迪丽热巴的作品有什么')
  56.     print(result)
  57.     print("大模型+知识库后回答的结果")
  58.     result = application.get_knowledge_based_answer('迪丽热巴的作品有什么')
  59.     print(result)

最终上述代码运行的结果如下:加入知识库后结果比没加之前好了很多,而且也能给出参考的文档是哪一篇。

是不是和new_bing chat返回结果很像。

示例结果

当然如果知识库里面没有结果,问答系统还是很答非所问,甚至会乱拼接知识。

目前也没有特别好的方式去完全杜绝这个问题,唯一能做的就是微调大模型或者调整你的prompt,prompt的微调也是一个比较重要的课。

结语

至此本文介绍了一下:

  1. 如何利用 知识库+LLM去构建一个基于知识库的问答系统的基本架构,而其中很多模块都可以进行丰富和优化,比如文本分块模块,文本向量化模块,LLM模块都可以替换成其他的模型。

  2. 如何利用langchain整合这些模块,langchain现在在ai圈非常火,并且还在成长。大家可以关注一下这个开源库。

大模型现在还有很多问题待解决,而且其的应用之路还有很多地方可以去探索,希望大家借此文章了解一下大模型的缺陷以及一些应用方法。

参考

https://github.com/imClumsyPanda/langchain-ChatGLM

https://github.com/yanqiangmiff


ChatGPT狂飙160天,世界已经不是之前的样子。

新建了人工智能中文站https://ai.weoknow.com
每天给大家更新可用的国内可用chatGPT资源

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/81320
推荐阅读
相关标签
  

闽ICP备14008679号