Chroma + Ollama 搭建本地RAG应用
本篇文章我们将基于Ollama
本地运行大语言模型(LLM
),并结合ChormaDB
、Langchain
来建立一个小型的基于网页内容进行本地问答的RAG
应用。
概念介绍
先简单了解下这些术语:
LLM
(A large language model
) 是通过使用海量的文本数据集(书籍、网站等)训练出来的,具备通用语言理解和生成的能力。虽然它可以推理许多内容,但它们的知识仅限于特定时间点之前用于训练的数据。
[LangChain] 是一个用于开发由大型语言模型(LLM
)驱动的应用程序的框架。提供了丰富的接口、组件、能力简化了构建LLM
应用程序的过程。
[Ollama] 是一个免费的开源框架,可以让大模型很容易的运行在本地电脑上。
RAG
(Retrieval Augmented Generation
)是一种利用额外数据增强 LLM
知识的技术,它通过从外部数据库获取当前或相关上下文信息,并在请求大型语言模型(LLM
)生成响应时呈现给它,从而解决了生成不正确或误导性信息的问题。
工作流程图解如下:
基于上述RAG
步骤,接下来我们将使用代码完成它。
开始搭建
1. 依据Ollama
使用指南完成大模型的本地下载和的运行。
# LLM
ollama pull llama3
# Embedding Model
ollama pull nomic-embed-text
2. 安装langchain
、langchain-community
、bs4
pip install langchain langchain-community bs4
3. 初始化langchain
提供的Ollama
对象
from langchain_community.llms import Ollama
from langchain.callbacks.manager import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
# 1. 初始化llm, 让其流式输出
llm = Ollama(model="llama3",
temperature=0.1,
top_p=0.4,
callback_manager=CallbackManager([StreamingStdOutCallbackHandler()])
)
temperature
控制文本生成的创造性,为0
时响应是可预测,始终选择下一个最可能的单词,这对于事实和准确性非常重要的答案是非常有用的。为 1
时生成文本会选择更多的单词,会产生更具创意但不可能预测的答案。
top_p
或 核心采样 决定了生成时要考虑多少可能的单词。高top_p
值意味着模型会考虑更多可能的单词,甚至是可能性较低的单词,从而使生成的文本更加多样化。
较低的temperature
和较高的top_p
,可以产生具有创意的连贯文字。 由于temperature
较低,答案通常具有逻辑性和连贯性,但由于top_p
较高,答案仍然具有丰富的词汇和观点。比较适合生成信息类文本,内容清晰且能吸引读者。
较高的temperature
和较低的top_p
,可能会把单词以难以预测的方式组合在一起。 生成的文本创意高,会出现意想不到的结果,适合创作。
4. 获取RAG检索内容并分块
#`BeautifulSoup'解析网页内容:按照标签、类名、ID 等方式来定位和提取你需要的内容
import bs4
#Load HTML pages using `urllib` and parse them with `BeautifulSoup'
from langchain_community.document_loaders import WebBaseLoader
#文本分割
from langchain_text_splitters import RecursiveCharacterTextSplitter
loader = WebBaseLoader(
web_paths=("https://vuejs.org/guide/introduction.html#html",),
bs_kwargs=dict(
parse_only=bs4.SoupStrainer(
class_=("content",),
# id=("article-root",)
)
),
)
docs = loader.load()
# chunk_overlap:分块的重叠部分
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
chunk_overlap
:分块的重叠部分,重叠有助于降低将语句与与其相关的重要上下文分开的可能性。 chunk_size
: 分块的大小,合理的分词设置会提高RAG
的效果
- 内容基于本地的词嵌入模型
nomic-embed-text
嵌入向量数据库中
# 向量嵌入 ::: conda install onnxruntime -c conda-forge
from langchain_community.vectorstores import Chroma
# 有许多嵌入模型
from langchain_community.embeddings import OllamaEmbeddings
# 基于ollama运行嵌入模型 nomic-embed-text : A high-performing open embedding model with a large token context window.
vectorstore = Chroma.from_documents(documents=splits,
embedding=OllamaEmbeddings(model="nomic-embed-text"))
# 相似搜索
# vectorstore.similarity_search("vue")
此处的嵌入模型也可以使用其他的比如llama3
、mistral
,但是在本地运行太慢了,它们和nomic-embed-text
一样不支持中文的词嵌入。如果想试试建立一个中文的文档库,可以试试 herald/dmeta-embedding-zh
词嵌入的模型,支持中文。
ollama pull herald/dmeta-embedding-zh:latest
- 设置
Prompt
规范输出
from langchain_core.prompts import PromptTemplate
prompt = PromptTemplate(
input_variables=['context', 'question'],
template=
"""You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the
question. you don't know the answer, just say you don't know
without any explanation Question: {question} Context: {context} Answer:""",
)
- 基于
langchain
实现检索问答
from langchain.chains import RetrievalQA
# 向量数据库检索器
retriever = vectorstore.as_retriever()
qa_chain = RetrievalQA.from_chain_type(
llm,
retriever=retriever,
chain_type_kwargs={"prompt": prompt}
)
# what is Composition API?
question = "what is vue?"
result = qa_chain.invoke({"query": question})
# output
# I think I know this one! Based on the context,
# Vue is a JavaScript framework for building user interfaces
# that builds on top of standard HTML, CSS, and JavaScript.
# It provides a declarative way to use Vue primarily in
# low-complexity scenarios or for building full applications with
# Composition API + Single-File Components.
如果我问的问题与文档无关它的回答是怎样呢?
question = "what is react?"
result = qa_chain.invoke({"query": question})
最终执行后输出了I don't know.
。
构建用户界面
Gradio
是一个用于构建交互式机器学习界面的Python
库。Gradio
使用非常简单。你只需要定义一个有输入和输出的函数,然后Gradio
将自动为你生成一个界面。用户可以在界面中输入数据,然后观察模型的输出结果。
整合上述代码,构建可交互的UI:
import gradio as gr
from langchain_community.llms import Ollama
from langchain.callbacks.manager import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import OllamaEmbeddings
from langchain.chains import RetrievalQA
from langchain_core.prompts import PromptTemplate
def init_ollama_llm(model, temperature, top_p):
return Ollama(model=model,
temperature=temperature,
top_p=top_p,
callback_manager=CallbackManager([StreamingStdOutCallbackHandler()])
)
def content_web(url):
loader = WebBaseLoader(
web_paths=(url,),
)
docs = loader.load()
# chunk_overlap:分块的重叠部分,重叠有助于降低将语句与与其相关的重要上下文分开的可能性,
# 设置了chunk_overlap效果会更好
# 合理的分词会提高RAG的效果
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
return splits
def chroma_retriever_store_content(splits):
# 基于ollama运行嵌入模型 nomic-embed-text : A high-performing open embedding model with a large token context window.
vectorstore = Chroma.from_documents(documents=splits,
embedding=OllamaEmbeddings(model="nomic-embed-text"))
return vectorstore.as_retriever()
def rag_prompt():
return PromptTemplate(
input_variables=['context', 'question'],
template=
"""You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the
question. you don't know the answer, just say you don't know
without any explanation Question: {question} Context: {context} Answer:""",
)
def ollama_rag_chroma_web_content(web_url, question,temperature,top_p):
llm = init_ollama_llm('llama3', temperature, top_p)
splits = content_web(web_url)
retriever = chroma_retriever_store_content(splits)
qa_chain = RetrievalQA.from_chain_type(llm, retriever=retriever, chain_type_kwargs={"prompt": rag_prompt()})
return qa_chain.invoke({"query": question})["result"]
demo = gr.Interface(
fn=ollama_rag_chroma_web_content,
inputs=[gr.Textbox(label="web_url",value="https://vuejs.org/guide/introduction.html",info="爬取内容的网页地址"),
"text",
gr.Slider(0, 1,step=0.1),
gr.Slider(0, 1,step=0.1)],
outputs="text",
title="Ollama+RAG Example",
description="输入网页的URL,然后提问, 获取答案"
)
demo.launch()
运行后会输出网页地址Running on local URL: http://127.0.0.1:7860
, 打开后效果如下:
参考
如何学习AI大模型?
我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;
第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;
第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;
第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;
第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;
第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;
第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。
👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;
• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;
• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;
• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。
1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集
👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓
更多推荐
所有评论(0)