赞
踩
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的幻想问题。
具体的流程和上述new_bing chat的流程很像,但是多了一个步骤
1.将知识库的文本分块,并进行向量化;
2.用户的query向量化,并在知识库中进行检索,返回最相关的TOPN的文本块;
3.采用合适的prompt + 上述步骤搜索到的文本 一并输入给LLM;
4.利用LLM的语义理解能力和知识问答能力,生成问题的答案。
下图则是最近github上很火的一个基于chatGLM实现的一个基于知识库的问答系统的架构图:
https://github.com/imClumsyPanda/langchain-ChatGLM
原理图
本项目地址: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。
具体技细节就是利用nlp_bert_document-segmentation_chinese-base模型将文本分割后,利用text2vec-large-chinese向量化,最终构建一个faiss索引,并持久化。
- from langchain.document_loaders import UnstructuredFileLoader, TextLoader, DirectoryLoader
- from langchain.embeddings.huggingface import HuggingFaceEmbeddings
- from langchain.vectorstores import FAISS
- from config import Config
- from utils.AliTextSplitter import AliTextSplitter
-
-
- class DocumentService(object):
- def __init__(self):
-
- self.config = Config.vector_store_path
- self.embeddings = HuggingFaceEmbeddings(model_name=Config.embedding_model_name)
- self.docs_path = Config.docs_path
- self.vector_store_path = Config.vector_store_path
- self.vector_store = None
-
- def init_source_vector(self):
- """
- 初始化本地知识库向量
- :return:
- """
- loader = DirectoryLoader(self.docs_path, glob="**/*.txt", loader_cls=TextLoader)
- # 读取文本文件
- documents = loader.load()
- text_splitter = AliTextSplitter()
- # 使用阿里的分段模型对文本进行分段
- split_text = text_splitter.split_documents(documents)
- # 采用embeding模型对文本进行向量化
- self.vector_store = FAISS.from_documents(split_text, self.embeddings)
- # 把结果存到faiss索引里面
- self.vector_store.save_local(self.vector_store_path)
-
- def load_vector_store(self):
- self.vector_store = FAISS.load_local(self.vector_store_path, self.embeddings)
-
-
-
- if __name__ == '__main__':
- s = DocumentService()
- ###将文本分块向量化存储起来
- s.init_source_vector()
加载ChatYuan-large-v2 大语言模型,当然也可以选择ChatGLM或者Moss等。
- from typing import List, Optional
- from langchain.llms.base import LLM
- from langchain.llms.utils import enforce_stop_tokens
- from transformers import AutoModel, AutoTokenizer
- from config import Config
-
-
- class LLMService(LLM):
- max_token: int = 10000
- temperature: float = 0.1
- top_p = 0.9
- history = []
- tokenizer: object = None
- model: object = None
-
- def __init__(self):
- super().__init__()
-
- @property
- def _llm_type(self) -> str:
- return "LLM"
-
- def _call(self,
- prompt: str,
- stop: Optional[List[str]] = None) -> str:
- response, _ = self.model.chat(
- self.tokenizer,
- prompt,
- history=self.history,
- max_length=self.max_token,
- temperature=self.temperature,
- )
- if stop is not None:
- response = enforce_stop_tokens(response, stop)
- self.history = self.history + [[None, response]]
- return response
-
- def load_model(self, model_name_or_path: str = "ClueAI/ChatYuan-large-v2"):
- """
- 加载大模型LLM
- :return:
- """
- self.tokenizer = AutoTokenizer.from_pretrained(
- Config.llm_model_name,
- trust_remote_code=True
- )
- self.model = AutoModel.from_pretrained(model_name_or_path, trust_remote_code=True)
- self.model = self.model.eval()
-
- if __name__ == '__main__':
- chatLLM = LLMService()
- chatLLM.load_model()
- from langchain.chains import RetrievalQA
- from langchain.prompts.prompt import PromptTemplate
-
- from config import Config
- from document import DocumentService
- from llm import LLMService
-
-
- class LangChainApplication(object):
-
- def __init__(self):
- self.config = Config
- self.llm_service = LLMService()
- ###加载llm和知识库向量
- print("load llm model ")
- self.llm_service.load_model(model_name_or_path=self.config.llm_model_name)
- self.doc_service = DocumentService()
- print("load documents")
- self.doc_service.load_vector_store()
-
- def get_knowledge_based_answer(self, query,
- history_len=5,
- temperature=0.1,
- top_p=0.9,
- top_k=1,
- chat_history=[]):
- #定义prompt
- prompt_template = """基于以下已知信息,简洁和专业的来回答用户的问题。
- 如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息",不允许在答案中添加编造成分,答案请使用中文。
- 已知内容:
- {context}
- 问题:
- {question}"""
- prompt = PromptTemplate(template=prompt_template,
- input_variables=["context", "question"])
- self.llm_service.history = chat_history[-history_len:] if history_len > 0 else []
-
- self.llm_service.temperature = temperature
- self.llm_service.top_p = top_p
- # 声明一个知识库问答llm,传入之前初始化好的llm和向量知识搜索服务
- knowledge_chain = RetrievalQA.from_llm(
- llm=self.llm_service,
- retriever=self.doc_service.vector_store.as_retriever(
- search_kwargs={"k": top_k}),
- prompt=prompt)
-
- knowledge_chain.combine_documents_chain.document_prompt = PromptTemplate(
- input_variables=["page_content"], template="{page_content}")
- knowledge_chain.return_source_documents = True
-
- ### 基于知识库的问答
- result = knowledge_chain({"query": query})
- return result
-
- def get_llm_answer(self, query=''):
- prompt_template = """请回答下列问题:
- {}""".format(query)
- ### 基于大模型的问答
- result = self.llm_service._call(prompt_template)
- return result
-
-
- if __name__ == '__main__':
- application = LangChainApplication()
- print("大模型自己回答的结果")
- result = application.get_llm_answer('迪丽热巴的作品有什么')
- print(result)
- print("大模型+知识库后回答的结果")
- result = application.get_knowledge_based_answer('迪丽热巴的作品有什么')
- print(result)
最终上述代码运行的结果如下:加入知识库后结果比没加之前好了很多,而且也能给出参考的文档是哪一篇。
是不是和new_bing chat返回结果很像。
示例结果
当然如果知识库里面没有结果,问答系统还是很答非所问,甚至会乱拼接知识。
目前也没有特别好的方式去完全杜绝这个问题,唯一能做的就是微调大模型或者调整你的prompt,prompt的微调也是一个比较重要的课。
至此本文介绍了一下:
如何利用 知识库+LLM去构建一个基于知识库的问答系统的基本架构,而其中很多模块都可以进行丰富和优化,比如文本分块模块,文本向量化模块,LLM模块都可以替换成其他的模型。
如何利用langchain整合这些模块,langchain现在在ai圈非常火,并且还在成长。大家可以关注一下这个开源库。
大模型现在还有很多问题待解决,而且其的应用之路还有很多地方可以去探索,希望大家借此文章了解一下大模型的缺陷以及一些应用方法。
https://github.com/imClumsyPanda/langchain-ChatGLM
https://github.com/yanqiangmiff
ChatGPT狂飙160天,世界已经不是之前的样子。
新建了人工智能中文站https://ai.weoknow.com
每天给大家更新可用的国内可用chatGPT资源
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。