TASK04【Datawhale 組隊學習】構建RAG應用

目錄

  • 將LLM接入LangChain
  • 構建檢索問答鏈
  • 運行成功圖
  • 遇到的問題

langchain可以便捷地調用大模型,并將其結合在以langchain為基礎框架搭建的個人應用中。

將LLM接入LangChain

  1. from langchain_openai import ChatOpenAI
  2. 實例化一個 ChatOpenAI 類,實例化時傳入超參數來控制回答,配置API密鑰
  3. llm.invoke(“prompt”)
  4. 提示模板(PromptTemplates):該文本提供有關當前特定任務的附加上下文。prompt=“模板”,text:用戶輸入 prompt.format(text=text)
    聊天模型的接口是基于消息(message),而不是原始的文本,PromptTemplates 也可以用于產生消息列表,在這種樣例中prompt不僅包含了輸入內容信息,也包含了每條message的信息(角色、在列表中的位置等)。
    一個ChatPromptTemplate是一個ChatMessageTemplate 的列表。每個 ChatMessageTemplate 包含格式化該聊天消息的說明(其角色以及內容)。
  • 定義設定system_template,human_template是用戶的輸入
  • ChatPromptTemplate構造參數包含list下的兩個元組參數[
    (“system”, template),
    (“human”, human_template),
    ],這里可以添加更多的角色的消息
from langchain_core.prompts import ChatPromptTemplatetemplate = "你是一個翻譯助手,可以幫助我將 {input_language} 翻譯成 {output_language}."
human_template = "{text}"chat_prompt = ChatPromptTemplate([("system", template),("human", human_template),
])text = "我帶著比身體重的行李,\
游入尼羅河底,\
經過幾道閃電 看到一堆光圈,\
不確定是不是這里。\
"
messages  = chat_prompt.invoke({"input_language": "中文", "output_language": "英文", "text": text})
import os
# 新的導入語句os.environ['ZHIPUAI_API_KEY']="這里寫上自己的api"
api_key = os.environ["ZHIPUAI_API_KEY"] #
from zhipuai_llm import ZhipuaiLLM
from dotenv import find_dotenv, load_dotenv# 讀取本地/項目的環境變量。# find_dotenv()尋找并定位.env文件的路徑
# load_dotenv()讀取該.env文件,并將其中的環境變量加載到當前的運行環境中
# 如果你設置的是全局的環境變量,這行代碼則沒有任何作用。
_ = load_dotenv(find_dotenv())

在這里插入圖片描述

構建檢索問答鏈

我們可以使用LangChain的LCEL(LangChain Expression Language, LangChain表達式語言)來構建workflow,LCEL可以支持異步(ainvoke)、流式(stream)、批次處理(batch)等多種運行方式,同時還可以使用LangSmith無縫跟蹤。

from langchain_core.runnables import RunnableLambda
def combine_docs(docs):return "\n\n".join(doc.page_content for doc in docs)combiner = RunnableLambda(combine_docs)
retrieval_chain = retriever | combinerretrieval_chain.invoke("南瓜書是什么?")

LCEL中要求所有的組成元素都是Runnable類型,前面我們見過的ChatModel、PromptTemplate等都是繼承自Runnable類。上方的retrieval_chain是由檢索器retriever及組合器combiner組成的,由|符號串連,數據從左向右傳遞,即問題先被retriever檢索得到檢索結果,再被combiner進一步處理并輸出。

llm=zhipuai_model
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_core.output_parsers import StrOutputParsertemplate = """使用以下上下文來回答最后的問題。如果你不知道答案,就說你不知道,不要試圖編造答
案。最多使用三句話。盡量使答案簡明扼要。請你在回答的最后說“謝謝你的提問!”。
{context}
問題: {input}
"""
# 將template通過 PromptTemplate 轉為可以在LCEL中使用的類型
prompt = PromptTemplate(template=template)qa_chain = (RunnableParallel({"context": retrieval_chain, "input": RunnablePassthrough()})| prompt| llm| StrOutputParser()
)
question_1 = "什么是南瓜書?"
question_2 = "Prompt Engineering for Developer是誰寫的?"
result = qa_chain.invoke(question_1)
print("大模型+知識庫后回答 question_1 的結果:")
print(result)
result = qa_chain.invoke(question_2)
print("大模型+知識庫后回答 question_2 的結果:")
print(result)
llm.invoke(question_1).content

在這里插入圖片描述
在這里插入圖片描述

# 無歷史記錄
messages = qa_prompt.invoke({"input": "南瓜書是什么?","chat_history": [],"context": ""}
)
for message in messages.messages:print(message.content)

在這里插入圖片描述

# 有歷史記錄
messages = qa_prompt.invoke({"input": "你可以介紹一下他嗎?","chat_history": [("human", "西瓜書是什么?"),("ai", "西瓜書是指周志華老師的《機器學習》一書,是機器學習領域的經典入門教材之一。"),],"context": ""}
)
for message in messages.messages:print(message.content)

在這里插入圖片描述

import os
import sys
from zhipuai_llm import ZhipuaiLLM
os.environ['ZHIPUAI_API_KEY']=""
api_key = os.environ["ZHIPUAI_API_KEY"] #填寫控制臺中獲取的 APIKey 信息sys.path.append(os.getcwd())# 將父目錄放入系統路徑中import streamlit as st
# from langchain_openai import ChatOpenAIfrom langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableBranch, RunnablePassthrough
from zhipuai_embedding import ZhipuAIEmbeddings
from langchain_community.vectorstores import Chromadef get_retriever():# 定義 Embeddingsembedding = ZhipuAIEmbeddings()# 向量數據庫持久化路徑persist_directory = 'D:\\code\\llm_universe\\chroma'# 加載數據庫vectordb = Chroma(persist_directory=persist_directory,embedding_function=embedding)return vectordb.as_retriever()
def combine_docs(docs):return "\n\n".join(doc.page_content for doc in docs["context"])def get_qa_history_chain():retriever = get_retriever()zhipuai_model = ZhipuaiLLM(model_name="glm-4-plus", temperature=0.1, api_key=api_key)llm = zhipuai_modelcondense_question_system_template = ("請根據聊天記錄總結用戶最近的問題,""如果沒有多余的聊天記錄則返回用戶的問題。")condense_question_prompt = ChatPromptTemplate([("system", condense_question_system_template),("placeholder", "{chat_history}"),("human", "{input}"),])retrieve_docs = RunnableBranch((lambda x: not x.get("chat_history", False), (lambda x: x["input"]) | retriever, ),condense_question_prompt | llm | StrOutputParser() | retriever,)system_prompt = ("你是一個問答任務的助手。 ""請使用檢索到的上下文片段回答這個問題。 ""如果你不知道答案就說不知道。 ""請使用簡潔的話語回答用戶。""\n\n""{context}")qa_prompt = ChatPromptTemplate.from_messages([("system", system_prompt),("placeholder", "{chat_history}"),("human", "{input}"),])qa_chain = (RunnablePassthrough().assign(context=combine_docs)| qa_prompt| llm| StrOutputParser())qa_history_chain = RunnablePassthrough().assign(context = retrieve_docs, ).assign(answer=qa_chain)return qa_history_chaindef gen_response(chain, input, chat_history):response = chain.stream({"input": input,"chat_history": chat_history})for res in response:if "answer" in res.keys():yield res["answer"]
def main():st.markdown('### 🦜🔗 動手學大模型應用開發')# st.session_state可以存儲用戶與應用交互期間的狀態與數據# 存儲對話歷史if "messages" not in st.session_state:st.session_state.messages = []# 存儲檢索問答鏈if "qa_history_chain" not in st.session_state:st.session_state.qa_history_chain = get_qa_history_chain()# 建立容器 高度為500 pxmessages = st.container(height=550)# 顯示整個對話歷史for message in st.session_state.messages: # 遍歷對話歷史with messages.chat_message(message[0]): # messages指在容器下顯示,chat_message顯示用戶及ai頭像st.write(message[1]) # 打印內容if prompt := st.chat_input("Say something"):# 將用戶輸入添加到對話歷史中st.session_state.messages.append(("human", prompt))# 顯示當前用戶輸入with messages.chat_message("human"):st.write(prompt)# 生成回復answer = gen_response(chain=st.session_state.qa_history_chain,input=prompt,chat_history=st.session_state.messages)# 流式輸出with messages.chat_message("ai"):output = st.write_stream(answer)# 將輸出存入st.session_state.messagesst.session_state.messages.append(("ai", output))if __name__ == "__main__":main()

運行成功圖

在這里插入圖片描述

遇到的問題

解決了一個很久以來都覺得奇怪的問題,pip的下載的包是依據與conda虛擬環境的,jupyter內核也有運行的conda虛擬環境,這些都是相互依賴的,我出現的問題是jupyternotebook運行在環境2的,而直接pip下載的包是在環境1里面的,所以需要conda activate 環境2之后再進行包的下載。jupyter notebook的python核版本可以自己進行設置,但是如果在環境中運行了!python --version可能顯示的是環境1的version。使用import sys print(sys.executable)可以查看當前jupyternotebook運行的python的環境。
在這里插入圖片描述

在這里插入圖片描述

“D:\anaconda\set\share\jupyter\kernels\python3_10_13”這里可以修改運行的python核的路徑,直接進行復制
在這里插入圖片描述
在這里插入圖片描述
再修改argv的路徑就行。display_name和文件夾的名字需要相同

元組tuple()
列表list[]
字典dictionary{“key”:“value”,“key”:“value”}
集合set{a,b,c}
數組array

import array
arr = array.array("i",[1,2,3])

隊列:queue

from collections import deque#雙端
q = deque([1,2,3])
q.append(4)
q.popleft()#隊頭刪除,返回1

堆:heap

import heapq
heap = [3,1,2]
heapq.heapify(heap)#轉換為最小堆
heapq.heappush(heap,0)# 插入 元素0
heapq.heappop(heap)#彈出最小元素

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/906494.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/906494.shtml
英文地址,請注明出處:http://en.pswp.cn/news/906494.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

springAI調用deepseek模型使用硅基流動api的配置信息

查看springai的官方文檔,調用deepseek的格式如下: spring.ai.deepseek.api-key${your-api-key} spring.ai.deepseek.chat.options.modeldeepseek-chat spring.ai.deepseek.chat.options.temperature0.8 但是硅基流動的格式不是這樣,這個傘兵…

SpringMVC 通過ajax 實現文件的上傳

使用form表單在springmvc 項目中上傳文件,文件上傳成功之后往往會跳轉到其他的頁面。但是有的時候,文件上傳成功的同時,并不需要進行頁面的跳轉,可以通過ajax來實現文件的上傳 下面我們來看看如何來實現: 方式1&…

Docker安裝Fluentd采集中間件

Fluentd 簡介 :Fluentd 是一個高性能、可擴展的數據收集與聚合工具,能夠統一數據收集和消費,實現各種數據源到各種數據接收器的高效傳輸,廣泛應用于日志收集等領域。 功能特點 : 統一日志收集 :支持從各種…

07SpringMVC底層形象解析

目錄 一、基于餐廳比喻的代碼示例 ,幫助你理解各組件間的協作關系 1. DispatcherServlet 配置(服務員) 2. HandlerMapping 配置(菜單索引) 3. Controller 實現(廚師) 4. Service 層&#x…

eclipse 生成函數說明注釋

在Eclipse中生成函數說明注釋(JavaDoc風格)可以通過以下方法實現: 快捷鍵方式: 將光標放在函數上方輸入/**后按回車鍵Eclipse會自動生成包含參數和返回值的注釋模板 菜單方式: 選中函數點擊菜單欄 Source > Gen…

【題解-洛谷】P6180 [USACO15DEC] Breed Counting S

題目:P6180 [USACO15DEC] Breed Counting S 題目描述 Farmer John 的 N N N 頭奶牛,從左到右編號為 1 …

基于Android的XX校園交流APP

開發語言:Java框架:ssmAndroidJDK版本:JDK1.8服務器:tomcat7數據庫:mysql 5.7數據庫工具:Navicat12開發軟件:eclipse/myeclipse/ideaMaven包:Maven3.3.9 系統展示 APP登錄 APP首頁…

25、工業防火墻 - 工控網絡保護 (模擬) - /安全與維護組件/industrial-firewall-dcs-protection

76個工業組件庫示例匯總 工業防火墻 - 工控網絡保護 (模擬) 概述 這是一個交互式的 Web 組件,旨在模擬工業防火墻在保護關鍵工控網絡(特別是 DCS - 分布式控制系統)免受網絡攻擊(如勒索軟件傳播)方面的核心功能。組件通過可視化簡化的網絡拓撲、模擬網絡流量、應用防火…

kotlin flow的兩種SharingStarted策略的區別

一 兩種 SharingStarted 策略的區別: SharingStarted.Eagerly: 立即開始收集上游流,即使沒有下游訂閱者持續保持活躍狀態,直到 ViewModel 被清除優點:響應更快,數據始終保持最新缺點:消耗更多資源&#x…

Windows_RustRover Rust語言開發環境構建

Windows_RustRover Rust語言開發環境構建 一、Rust語言簡介(一)起源與發展(二)語言特點(三)應用場景(四)社區與生態 二、RustRover(一)主要功能(二…

XCOSnTh-fatfsShell

#include "XCOSnTh.h" #include "ff.h" #include "stdio.h" static char pwd[1024]"1:"; static char pwdCount2; FRESULT lsExe(char *path,int(*printf)(const char* format, ...)) {FRESULT res;DIR dir;FILINFO fno;// 打開根目錄…

篇章十 消息持久化(二)

目錄 1.消息持久化-創建MessageFileManger類 1.1 創建一個類 1.2 創建關于路徑的方法 1.3 定義內部類 1.4 實現消息統計文件讀寫 1.5 實現創建消息目錄和文件 1.6 實現刪除消息目錄和文件 1.7 實現消息序列化 1. 消息序列化的一些概念: 2. 方案選擇&#xf…

中間件-seata

分布式事務seata 角色組成角色指責AT模式TCC模式 角色組成 TC:事務協調者,維護全局和分支事務的狀態,驅動全局事務提交或回滾。TM:事務管理者,定義全局事務的范圍:開始全局事務、提交或回滾全局事務。RM&am…

python代碼繪制某只股票最近90天的K線圖、均線、量能圖

運行代碼,要求輸入股票代碼和名稱,其他參數可省略 import akshare as ak import matplotlib.pyplot as plt import pandas as pd import mplfinance as mpf import matplotlib.dates as mdates import numpy as np import os from datetime import date…

Xilinx 7Series\UltraScale 在線升級FLASH STARTUPE2和STARTUPE3使用

一、FPGA 在線升級 FPGA 在線升級FLASH時,一般是通過邏輯生成SPI接口操作FLASH,當然也可以通過其他SOC經FPGA操作FLASH,那么FPGA就要實現在啟動后對FLASH的控制。 對于7Series FPGA,只有CCLK是專用引腳,SPI接口均為普…

Azure 應用服務中的異常處理、日志記錄和通知:綜合指南

簡介 Azure 應用服務是基于云的應用程序,使開發人員能夠在云上構建、部署和管理應用程序。與任何應用程序一樣,制定適當的異常處理、日志記錄和通知實踐至關重要,以確保應用程序平穩運行,并快速識別和解決任何問題。在本篇博文中&…

Java 應用如何實現 HTTPS:加密數據傳輸的實用指南

Java 應用如何實現 HTTPS:加密數據傳輸的實用指南 在當今的互聯網環境中,數據安全至關重要,HTTPS 作為加密的數據傳輸協議,為 Java 應用提供了安全通信的保障。本文將深入探討 Java 應用如何實現 HTTPS,通過詳細代碼實…

域名與DNS詳解

域名與DNS詳解 一、核心概念 域名(Domain Name) 定義:人類可讀的網絡地址標識(如 www.google.com)作用:替代復雜IP地址(類似"手機通訊錄"功能) DNS(Domain …

c++20引入的三路比較操作符<=>

目錄 一、簡介 二、三向比較的返回類型 2.1 std::strong_ordering 2.2 std::weak_ordering 2.3 std::partial_ordering 三、對基礎類型的支持 四、自動生成的比較運算符函數 4.1 std::rel_ops的作用 4.2 使用<> 五、兼容他舊代碼 一、簡介 c20引入了三路比較操…

計算機網絡相關面試題

一、HTTP1.1和HTTP2的區別 HTTP/1&#xff08;主要指 HTTP/1.1&#xff09;和 HTTP/2 是 Web 協議發展中的兩個重要版本&#xff0c;二者在性能、協議機制和功能特性上有顯著差異。以下從多個維度對比分析&#xff0c;并結合具體案例說明&#xff1a; 一、連接與請求處理方式 1…