LLM之RAG实战(十九)| 利用LangChain、OpenAI、ChromaDB和Streamlit构建RAG

       生成式人工智能以其创造与上下文相关内容的能力彻底改变了技术,开创了人工智能可能性的新时代。其核心是检索增强生成(RAG),将信息检索与LLM相结合,从外部文档中产生智能、知情的响应。

     本文将深入研究使用ChromaDB构建RAG驱动的LLM应用程序,ChromaDB以其对大型数据集的高效处理而闻名。

一、环境准备

      要构建基于RAG的LLM应用程序,需要准备如下环境配置:

  • python(下载地址:https://www.python.org/downloads/)
  • OpenAI API Key(获取地址:https://platform.openai.com/signup)

        以及对Python和web API的基本理解。

二、代码实现

2.1 创建并导航到项目目录

在终端中,创建一个新目录并导航到该目录:

mkdir rag_lmm_applicationcd rag_lmm_application

2.2 创建虚拟环境

虚拟环境可以隔离不同的python环境,创建命令如下所示:

python -m venv venv

激活虚拟环境。对于Mac/Linux用户,请使用:

source venv/bin/activate

对于Windows用户:

venv\Scripts\activate

2.3 安装所需的包

安装基本库:

pip install -r requirements.txt

PS:确保requirements.txt文件中包含所有必要的依赖项。

       通过上述步骤,环境已经准备就绪,下面开始使用ChromaDB构建最先进的RAG聊天应用程序。

2.4 加载和处理文档

      下面使用LangChain来加载各种文档格式,如PDF、DOCX和TXT,这对于外部数据访问、确保高效的数据处理以及为后续阶段保持统一的数据准备至关重要。代码如下:

# loading PDF, DOCX and TXT files as LangChain Documentsdef load_document(file):    import os    name, extension = os.path.splitext(file)    if extension == '.pdf':        from langchain.document_loaders import PyPDFLoader        print(f'Loading {file}')        loader = PyPDFLoader(file)    elif extension == '.docx':        from langchain.document_loaders import Docx2txtLoader        print(f'Loading {file}')        loader = Docx2txtLoader(file)    elif extension == '.txt':        from langchain.document_loaders import TextLoader        loader = TextLoader(file)    else:        print('Document format is not supported!')        return None    data = loader.load()    return data

       数据分块对RAG系统非常重要,对数据进行分块以便于嵌入,这确保可以保留高效的上下文和信息检索。代码如下:

# splitting data in chunksdef chunk_data(data, chunk_size=256, chunk_overlap=20):    from langchain.text_splitter import RecursiveCharacterTextSplitter    text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)    chunks = text_splitter.split_documents(data)    return chunks

2.5 使用OpenAI和ChromaDB创建嵌入

       使用OpenAI大模型来创建嵌入,并将它们高效地存储在ChromaDB中,可以快速检索信息,代码如下所示:

# create embeddings using OpenAIEmbeddings() and save them in a Chroma vector storedef create_embeddings(chunks):    embeddings = OpenAIEmbeddings()    vector_store = Chroma.from_documents(chunks, embeddings)    # if you want to use a specific directory for chromadb    # vector_store = Chroma.from_documents(chunks, embeddings, persist_directory='./mychroma_db')    return vector_store

2.6 使用Streamlight构建聊天界面

       Streamlit的简单性在我们的RAG LLM应用程序中大放异彩,可以毫不费力地将用户输入链接到后端处理。通过Streamlit的初始化和布局设计,用户可以上传文档和管理数据。后端处理这些输入,直接在Streamlit界面中返回响应,展示了前端和后端操作的无缝集成。下面是一个代码片段来说明设置:

def ask_and_get_answer(vector_store, q, k=3):    from langchain.chains import RetrievalQA    from langchain.chat_models import ChatOpenAI    llm = ChatOpenAI(model='gpt-3.5-turbo', temperature=1)    retriever = vector_store.as_retriever(search_type='similarity', search_kwargs={'k': k})    chain = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=retriever)    answer = chain.run(q)    return answer# calculate embedding cost using tiktokendef calculate_embedding_cost(texts):    import tiktoken    enc = tiktoken.encoding_for_model('text-embedding-ada-002')    total_tokens = sum([len(enc.encode(page.page_content)) for page in texts])    # print(f'Total Tokens: {total_tokens}')    # print(f'Embedding Cost in USD: {total_tokens / 1000 * 0.0004:.6f}')    return total_tokens, total_tokens / 1000 * 0.0004# clear the chat history from streamlit session statedef clear_history():    if 'history' in st.session_state:        del st.session_state['history']if __name__ == "__main__":    import os    # loading the OpenAI api key from .env    from dotenv import load_dotenv, find_dotenv    load_dotenv(find_dotenv(), override=True)    st.image('img.png')    st.subheader('LLM Question-Answering Application 🤖')    with st.sidebar:        # text_input for the OpenAI API key (alternative to python-dotenv and .env)        api_key = st.text_input('OpenAI API Key:', type='password')        if api_key:            os.environ['OPENAI_API_KEY'] = api_key        # file uploader widget        uploaded_file = st.file_uploader('Upload a file:', type=['pdf', 'docx', 'txt'])        # chunk size number widget        chunk_size = st.number_input('Chunk size:', min_value=100, max_value=2048, value=512, on_change=clear_history)        # k number input widget        k = st.number_input('k', min_value=1, max_value=20, value=3, on_change=clear_history)        # add data button widget        add_data = st.button('Add Data', on_click=clear_history)        if uploaded_file and add_data: # if the user browsed a file            with st.spinner('Reading, chunking and embedding file ...'):                # writing the file from RAM to the current directory on disk                bytes_data = uploaded_file.read()                file_name = os.path.join('./', uploaded_file.name)                with open(file_name, 'wb') as f:                    f.write(bytes_data)                data = load_document(file_name)                chunks = chunk_data(data, chunk_size=chunk_size)                st.write(f'Chunk size: {chunk_size}, Chunks: {len(chunks)}')                tokens, embedding_cost = calculate_embedding_cost(chunks)                st.write(f'Embedding cost: ${embedding_cost:.4f}')                # creating the embeddings and returning the Chroma vector store                vector_store = create_embeddings(chunks)                # saving the vector store in the streamlit session state (to be persistent between reruns)                st.session_state.vs = vector_store                st.success('File uploaded, chunked and embedded successfully.')

       上面的代码显示了如何在Streamlit中创建文本输入字段并处理用户输入。通过这种设置,用户可以无缝直观地与人工智能应用程序交互。

2.7 检索答案和增强用户交互

       我们的RAG聊天应用程序利用了LangChain的RetrievalQA和ChromaDB,通过从ChromaDB的嵌入式数据中提取的相关、准确的信息有效地响应用户查询,体现了先进的Generative AI功能。

       下面的代码片段展示了Streamlit应用程序的实现:

# user's question text input widget    q = st.text_input('Ask a question about the content of your file:')    if q: # if the user entered a question and hit enter        if 'vs' in st.session_state: # if there's the vector store (user uploaded, split and embedded a file)            vector_store = st.session_state.vs            st.write(f'k: {k}')            answer = ask_and_get_answer(vector_store, q, k)            # text area widget for the LLM answer            st.text_area('LLM Answer: ', value=answer)            st.divider()            # if there's no chat history in the session state, create it            if 'history' not in st.session_state:                st.session_state.history = ''            # the current question and answer            value = f'Q: {q} \nA: {answer}'            st.session_state.history = f'{value} \n {"-" * 100} \n {st.session_state.history}'            h = st.session_state.history            # text area widget for the chat history            st.text_area(label='Chat History', value=h, key='history', height=400)

       此代码集成了Streamlit中的用户输入和响应生成。使用ChromaDB的矢量数据,可以获得准确的答案,增强聊天应用程序的交互性,并提供信息丰富的人工智能对话。

三、结论

       本文,我们探讨了使用OpenAI、ChromaDB和Streamlit构建LLM应用程序的复杂性,介绍了设置环境、处理文档、创建和存储嵌入以及构建用户友好的聊天界面,展示了RAG和ChromaDB的强大组合。

       要运行应用程序,请在终端中执行以下命令:

streamlit run ./chat_with_documents.py

       现在,可以通过导航到http://localhost:8501来测试该应用程序。

参考文献:

[1] https://medium.com/@oladimejisamuel/unlocking-the-power-of-generativeai-building-a-cutting-edge-rag-chat-application-with-chromadb-c5c994ccc584

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/638102.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

三.Winform使用Webview2加载本地HTML页面

Winform使用Webview2加载本地HTML页面 往期目录创建Demo2界面创建HTML页面在Demo2窗体上添加WebView2和按钮加载HTML查看效果 往期目录 往期相关文章目录 专栏目录 创建Demo2界面 经过前面两小节 一.Winform使用Webview2(Edge浏览器核心) 创建demo(Demo1)实现回车导航到指定…

广和通AI解决方案“智”赋室外机器人迈向新天地!

大模型趋势下,行业机器人将具备更完善的交互与自主能力,逐步迈向AI 2.0时代,成为人工智能技术全面爆发的重要基础。随着行业智能化,更多机器人应用将从“室内”走向“室外”,承担更多高风险、高智能工作。复杂的室外环…

代码随想录二刷 | 二叉树 | 把二叉搜索树转换为累加树

代码随想录二刷 | 二叉树 | 把二叉搜索树转换为累加树 题目描述解题思路递归法迭代法 代码实现递归法迭代法 题目描述 538.把二叉搜索树转换为累加树 给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树&…

分布式 session

分布式 session 种 session 的时候需要注意范围,也就是 cookie.domain。 比如两个域名:a.heo.com,b.heo.com。如果要共享 cookie,可以种一个更高层的公共域名,比如 heo.com。 当服务器 A (localhost:808…

基于ECS服务器搭建FTP服务

vsftpd(very secure FTP daemon)是一款在Linux发行版中最受推崇的FTP服务器。vsftpd支持匿名访问和本地用户模式两种访问方式。匿名访问方式任何用户都可以访问搭建的FTP服务;本地用户模式只支持添加的本地用户访问搭建的FTP服务。 说明: 匿…

前端实现贪吃蛇功能

大家都玩过贪吃蛇小游戏,控制一条蛇去吃食物,然后蛇在吃到食物后会变大。本篇博客将会实现贪吃蛇小游戏的功能。 1.实现效果 2.整体布局 /*** 游戏区域样式*/ const gameBoardStyle {gridTemplateColumns: repeat(${width}, 1fr),gridTemplateRows: re…

新买电脑配置不低却卡顿?

目录 前言: 电脑卡顿的原因 Windows 10必做的系统优化 禁用 IP Helper 关闭系统通知 机械硬盘开启优化驱动器功能 开启存储感知 前言: 新买的电脑配置不低,但却卡顿甚至程序不反应,这是怎么回事儿? 其实并不…

《Linux C编程实战》笔记:Linux信号介绍

信号是一种软件中断,它提供了处理一种异步事件的方法,也是进程惟一的异步通信方式。在Linux系统中,根据POSIX标准扩展的信号机制,不仅可以用来通知某进程发生了什么事,还可以给进程传递数据。 信号的来源 信号的来源…

信号处理专题设计-基于边缘检测的数字图像分类识别

目录 一、实验目的 二、实验要求 三、实验原理 1.卷积神经网络(CNN)模型 2.边缘检测 3.形态学操作 4.鲁棒性 四、实验过程 1.数据预处理 2. 网络的构建 3.模型的训练 4.边缘检测和形态学操作相关代码 5.模型训练结果 6.关键信息的保存 五、实验测试与评估…

竞赛保研 机器视觉人体跌倒检测系统 - opencv python

0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 机器视觉人体跌倒检测系统 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数&…

【蓝桥杯日记】复盘第一篇——顺序结构

🚀前言 本期是一篇关于顺序结构的题目的复盘,通过复盘基础知识,进而把基础知识学习牢固!通过例题而进行复习基础知识。 🚩目录 前言 1.字符三角形 分析: 知识点: 代码如下 2. 字母转换 题目分析: 知…

C语言·预处理详解

1. 预定义符号 C语言设置了一些预定义符号,可以直接使用,预定义符号也是在预处理期间处理的 __FILE__ 进行编译的源文件 __LINE__ 文件当前的行号 __DATE__ 文件被编译的日期 __TIME__ 文件被编译的时间 __STDC__ 如果编译器遵循ANSI C,…

SpringCloud Aliba-Sentinel【下篇】-从入门到学废【6】

🤩java小课堂🤩 🌭🌭🌭 和 equals 的区别是什么?🥹🥹🥹 对于基本类型, 比较的是值;对于引用类型,比较的是地址;equals不能…

【现代密码学基础】详解完美安全与不可区分安全

目录 一. 介绍 二. 不可区分性试验 三. 不可区分性与完美安全 四. 例题 五. 小结 一. 介绍 敌手完美不可区分,英文写做perfect adversarial indistinguishability,其中adversarial经常被省略不写,在密码学的论文中经常被简称为IND安全。…

ICLR 2024 时间序列相关最新论文汇总,涉及transformer、GNN、大模型等热门领域

ICLR(International Conference on Learning Representations),国际公认的深度学习顶会之一,与AAAI、CVPR、ACL和NIPS等老牌学术会议齐名,由图灵奖巨头Yoshua Bengio和Yann LeCun牵头举办,在人工智能、统计…

Spring | Srping AOP (AOP简介、动态代理、基于“代理类”的AOP实现)

目录: 1.Spring AOP简介1.1 AOP简介1.2 AOP术语 2.动态代理2.1 JDK动态代理2.2 CGLIB代理 3.基于“代理类”的AOP实现3.1 Spring的通知类型3.2 ProxyFactoryBean ( 可通知.xml配置文件完成aop功能 ) 1.Spring AOP简介 1.1 AOP简介 Spring的AOP模块,是Spring框架体系…

SpringMVC获取参数与页面跳转

获取参数 第一种 直接当成方法的参数,需要与前台的name一致 相当于Request.getAttribute("username") Controller 第二种 使用对象接收 页面的name也要和对象的字段一致 创建一个对应的实体类 Controller 将参数更换为User对象就行 SpringMVC获取到…

P2P DMA并不是所有场景都会有性能提升

P2P (Peer-to-Peer) DMA技术理论上可以带来性能提升,特别是在特定的工作负载和场景下。例如,当两个高速设备(如GPU与NVMe SSD)需要频繁进行大量数据交换时,通过P2P DMA,数据可以直接在设备间传输&#xff0…

结构体内存对齐(面试重点)

结构体内存对齐 1. 结构体类型的声明1.1 结构体的概念1.1.1 结构的声明1.1.2 结构体变量的创建和初始化 1.2 结构的特殊声明1.3 结构的自引用 2. 结构体内存对齐2.1 对齐规则2.1.1 练习1:2.1.2 练习2:2.1.3 练习3:2.1.4 练习4: 2.2 offsetof宏的使用2.3 为什么存在内存对齐?2.…

electron + selenium报错: Server terminated early with status 1

解决办法: 这种错误一般是浏览器创建的某方法致命错误导致的,查看一下实例化driver的地方有哪些配置,着重看日志、用执行信息存储一类的配置,我的问题是日志文件夹改过了但没有创建 // 浏览器参数设置 const customArguments [-…