链载Ai

标题: RAG 开发实例 [打印本页]

作者: 链载Ai    时间: 10 小时前
标题: RAG 开发实例

ingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: medium;letter-spacing: normal;text-align: start;background-color: rgb(255, 255, 255);visibility: visible;">

ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;display: table;border-bottom: 2px solid rgb(15, 76, 129);color: rgb(63, 63, 63);visibility: visible;">引言

RAG 已经几乎可以说是 AI 入门应用,实现方式很多,低代码平台,手搓代码都可以实现,涉及到的核心技术包括,知识库、提示词工程、向量数据库、LLM、全文检索、 query 重写等。


本文介绍如何开发基于 RAG slack 问答机器人,整体架构如上图所示。示例代码参考:https://github.com/coldfire-x/aiagent-slackbot/tree/main 。

ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);">知识库

现在的LLM大语言模型,可以不做任何微调,zero-shot 的情况下,给出相对来说比较满意的答复,比如,你可以问它什么是 RAG,它可以给你非常好的答复。但是,LLM 大语言模型也有自身的局限性,训练时,无法感知到企业内部资料,缺乏对企业业务流程,业务领域的知识。

我们在做企业内部问答工具时,需要做 RAG,给 LLM 提供问题的上下文,让 LLM 能够基于领域知识,查询,总结,归纳出问题的答案。本文在做知识库时,一篇文章一个主题,文章的内容主题明确。同时,使用 markdown 格式,在文章中也包含了很多元数据信息,比如语言,背景知识,术语等。对LLM 来说也更好理解。

ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);">向量数据库

本实例使用的时 FAISS 向量数据库,使用 crontab,定时拉取更新知识(知识内容托管在 github),之后,存储到向量数据库。核心代码逻辑在,index_documents.py 文件内:

# Read the markdown filewithopen(file_path, encoding="utf-8")asfile:  content = file.read()
# Convert markdown to HTML and then extract text to remove markdown formattinghtml = markdown2.markdown(content)soup = BeautifulSoup(html,"html.parser")text = soup.get_text()
# Create a Document object with metadatarelative_path = os.path.relpath(file_path, directory_path)doc = Document( page_content=text, metadata={ "source": file_path, "filename": os.path.basename(file_path), "path": relative_path, },)
# index document# Add to vector storeifnotself.vector_store: self.vector_store = FAISS.from_documents( documents=documents, embedding=self.embeddings )else: self.vector_store.add_documents(documents)

ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);">query 重写

在实际的问答场景中,用户问的问题,可能非常粗糙,比如,我登录不了了,如何注册,2FA,如果直接拿这些 query 词去搜索知识库,可能搜不到知识,所以需要对用户的 query 做一次重写,可以是用规则做映射,也可以让 LLM 生产多 query 词,本文使用 langchian 的MultiQueryRetriever,在获取相关文档时,会自动做 query 重写。


重写后的 query,能检索到更多的数据:

#InitializeMultiQueryRetrieverretriever=MultiQueryRetriever.from_llm(retriever=vectorstore.as_retriever(),llm=llm)

ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);">混合检索(EnsembleRetriever)

在 RAG 系统中,不同的 retriever 有各自的优缺点,比如:


所以,在实际开发的过程中,组合了向量搜索 + 关键词搜索的方式,来提升检索能力,代码实现参考:

# Create keyword-based BM25 retrieverself.bm25_retriever = BM25Retriever.from_documents(self.documents)self.bm25_retriever.k =3# 获取 top 3 的文章
# Create semantic retrieverself.semantic_retriever = self.vector_store.as_retriever( search_kwargs={"k":5,"search_type":"similarity"})# 获取 top 5 的文章
# Create ensemble retriever (combines both approaches)self.hybrid_retriever = EnsembleRetriever( retrievers=[self.bm25_retriever, self.semantic_retriever], weights=[0.3,0.7], # Weight semantic search higher)# 分配不同 retriever 的权重,关键词搜索占 30%,语意搜索占 70%

代码中的权重,主要用于给检索到的文章评分,通常会按加权和计算, 公式中的 wbm25, wsemantic 就是代码中设定的权重:


ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;border-left: 3px solid rgb(15, 76, 129);color: rgb(63, 63, 63);">Prompt 优化

最后,对于 LLM,本质上是概率模型,无论给什么问题,它都会给出最有可能的回复(概率TOPn),出现所谓的幻觉。 所以,query LLM 大语言模型时,需要做提示词优化,给 LLM 加限制,一般情况下,提示词中,会特别写一句,如果没有检索到相关的内容,请直接回答不知道,避免 LLM 胡编乱造,产生影响。


到这里,基本上把核心的技术都涉及到了,如果要提升效果,涉及到的各个技术都有很大的优化空间,也需要做更细致的测试评估。


END







欢迎光临 链载Ai (https://www.lianzai.com/) Powered by Discuz! X3.5