【InternLM 實戰營筆記】基于 InternLM 和 LangChain 搭建MindSpore知識庫

InternLM 模型部署

準備環境

拷貝環境

/root/share/install_conda_env_internlm_base.sh InternLM

激活環境

conda activate InternLM

安裝依賴

# 升級pip
python -m pip install --upgrade pippip install modelscope==1.9.5
pip install transformers==4.35.2
pip install streamlit==1.24.0
pip install sentencepiece==0.1.99
pip install accelerate==0.24.1

模型下載

mkdir -p /root/data/model/Shanghai_AI_Laboratory
cp -r /root/share/temp/model_repos/internlm-chat-7b /root/data/model/Shanghai_AI_Laboratory/internlm-chat-7b

LangChain 相關環境配置

pip install langchain==0.0.292
pip install gradio==4.4.0
pip install chromadb==0.4.15
pip install sentence-transformers==2.2.2
pip install unstructured==0.10.30
pip install markdown==3.3.7

同時,我們需要使用到開源詞向量模型 Sentence Transformer:(我們也可以選用別的開源詞向量模型來進行 Embedding,目前選用這個模型是相對輕量、支持中文且效果較好的,同學們可以自由嘗試別的開源詞向量模型)

首先需要使用 huggingface 官方提供的 huggingface-cli 命令行工具。安裝依賴:

pip install -U huggingface_hub

然后在和 /root/data 目錄下新建python文件 download_hf.py,填入以下代碼:

  • resume-download:斷點續下
  • local-dir:本地存儲路徑。(linux環境下需要填寫絕對路徑)
import os# 下載模型
os.system('huggingface-cli download --resume-download sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 --local-dir /root/data/model/sentence-transformer')

如果下載速度慢可以使用鏡像下載將 download_hf.py 中的代碼修改為以下代碼:

import os# 設置環境變量
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'# 下載模型
os.system('huggingface-cli download --resume-download sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 --local-dir /root/data/model/sentence-transformer')

執行腳本

python download_hf.py

下載 NLTK 相關資源

下載

cd /root
git clone https://gitee.com/yzy0612/nltk_data.git  --branch gh-pages
cd nltk_data
mv packages/*  ./
cd tokenizers
unzip punkt.zip
cd ../taggers
unzip averaged_perceptron_tagger.zip

下載本項目代碼

cd /root/data
git clone https://github.com/InternLM/tutorial

知識庫搭建

數據收集

選擇mindspre docs代碼倉作為語料庫來源
地址:
https://gitee.com/mindspore/docs

# 進入到數據庫盤
cd /root/data
# clone 上述開源倉庫
git clone https://gitee.com/mindspore/docs.git

知識庫搭建的腳本

# 首先導入所需第三方庫
from langchain.document_loaders import UnstructuredFileLoader
from langchain.document_loaders import UnstructuredMarkdownLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
from tqdm import tqdm
import os# 獲取文件路徑函數
def get_files(dir_path):# args:dir_path,目標文件夾路徑file_list = []for filepath, dirnames, filenames in os.walk(dir_path):# os.walk 函數將遞歸遍歷指定文件夾for filename in filenames:# 通過后綴名判斷文件類型是否滿足要求if filename.endswith("_CN.md"):# 如果滿足要求,將其絕對路徑加入到結果列表file_list.append(os.path.join(filepath, filename))elif filename.endswith("_CN.txt"):file_list.append(os.path.join(filepath, filename))return file_list# 加載文件函數
def get_text(dir_path):# args:dir_path,目標文件夾路徑# 首先調用上文定義的函數得到目標文件路徑列表file_lst = get_files(dir_path)# docs 存放加載之后的純文本對象docs = []# 遍歷所有目標文件for one_file in tqdm(file_lst):file_type = one_file.split('.')[-1]if file_type == 'md':loader = UnstructuredMarkdownLoader(one_file)elif file_type == 'txt':loader = UnstructuredFileLoader(one_file)else:# 如果是不符合條件的文件,直接跳過continuedocs.extend(loader.load())return docs# 目標文件夾
tar_dir = ["/root/data/docs"
]# 加載目標文件
docs = []
for dir_path in tar_dir:docs.extend(get_text(dir_path))# 對文本進行分塊
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=150)
split_docs = text_splitter.split_documents(docs)# 加載開源詞向量模型
embeddings = HuggingFaceEmbeddings(model_name="/root/data/model/sentence-transformer")# 構建向量數據庫
# 定義持久化路徑
persist_directory = 'data_base/vector_db/chroma'
# 加載數據庫
vectordb = Chroma.from_documents(documents=split_docs,embedding=embeddings,persist_directory=persist_directory  # 允許我們將persist_directory目錄保存到磁盤上
)
# 將加載的向量數據庫持久化到磁盤上
vectordb.persist()

可以在 /root/data 下新建一個 demo目錄,將該腳本和后續腳本均放在該目錄下運行。運行上述腳本,即可在本地構建已持久化的向量數據庫,后續直接導入該數據庫即可,無需重復構建。

InternLM 接入 LangChain

腳本

from langchain.llms.base import LLM
from typing import Any, List, Optional
from langchain.callbacks.manager import CallbackManagerForLLMRun
from transformers import AutoTokenizer, AutoModelForCausalLM
import torchclass InternLM_LLM(LLM):# 基于本地 InternLM 自定義 LLM 類tokenizer : AutoTokenizer = Nonemodel: AutoModelForCausalLM = Nonedef __init__(self, model_path :str):# model_path: InternLM 模型路徑# 從本地初始化模型super().__init__()print("正在從本地加載模型...")self.tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)self.model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True).to(torch.bfloat16).cuda()self.model = self.model.eval()print("完成本地模型的加載")def _call(self, prompt : str, stop: Optional[List[str]] = None,run_manager: Optional[CallbackManagerForLLMRun] = None,**kwargs: Any):# 重寫調用函數system_prompt = """You are an AI assistant whose name is InternLM (書生·浦語).- InternLM (書生·浦語) is a conversational language model that is developed by Shanghai AI Laboratory (上海人工智能實驗室). It is designed to be helpful, honest, and harmless.- InternLM (書生·浦語) can understand and communicate fluently in the language chosen by the user such as English and 中文."""messages = [(system_prompt, '')]response, history = self.model.chat(self.tokenizer, prompt , history=messages)return response@propertydef _llm_type(self) -> str:return "InternLM"

將上述代碼封裝為 LLM.py,后續將直接從該文件中引入自定義的 LLM 類。

構建檢索問答鏈

整體腳本

from langchain.vectorstores import Chroma
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
import os# 定義 Embeddings
embeddings = HuggingFaceEmbeddings(model_name="/root/data/model/sentence-transformer")# 向量數據庫持久化路徑
persist_directory = 'data_base/vector_db/chroma'# 加載數據庫
vectordb = Chroma(persist_directory=persist_directory, embedding_function=embeddings
)from LLM import InternLM_LLM
llm = InternLM_LLM(model_path = "/root/data/model/Shanghai_AI_Laboratory/internlm-chat-7b")
llm.predict("你是誰")from langchain.prompts import PromptTemplate# 我們所構造的 Prompt 模板
template = """使用以下上下文來回答用戶的問題。如果你不知道答案,就說你不知道。總是使用中文回答。
問題: {question}
可參考的上下文:
···
{context}
···
如果給定的上下文無法讓你做出回答,請回答你不知道。
有用的回答:"""# 調用 LangChain 的方法來實例化一個 Template 對象,該對象包含了 context 和 question 兩個變量,在實際調用時,這兩個變量會被檢索到的文檔片段和用戶提問填充
QA_CHAIN_PROMPT = PromptTemplate(input_variables=["context","question"],template=template)from langchain.chains import RetrievalQAqa_chain = RetrievalQA.from_chain_type(llm,retriever=vectordb.as_retriever(),return_source_documents=True,chain_type_kwargs={"prompt":QA_CHAIN_PROMPT})# 檢索問答鏈回答效果
question = "什么是MindSpore"
result = qa_chain({"query": question})
print("檢索問答鏈回答 question 的結果:")
print(result["result"])# 僅 LLM 回答效果
result_2 = llm(question)
print("大模型回答 question 的結果:")
print(result_2)

部署 Web Demo

from langchain.vectorstores import Chroma
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
import os
from LLM import InternLM_LLM
from langchain.prompts import PromptTemplate
from langchain.chains import RetrievalQAdef load_chain():# 加載問答鏈# 定義 Embeddingsembeddings = HuggingFaceEmbeddings(model_name="/root/data/model/sentence-transformer")# 向量數據庫持久化路徑persist_directory = 'data_base/vector_db/chroma'# 加載數據庫vectordb = Chroma(persist_directory=persist_directory,  # 允許我們將persist_directory目錄保存到磁盤上embedding_function=embeddings)# 加載自定義 LLMllm = InternLM_LLM(model_path = "/root/data/model/Shanghai_AI_Laboratory/internlm-chat-7b")# 定義一個 Prompt Templatetemplate = """使用以下上下文來回答最后的問題。如果你不知道答案,就說你不知道,不要試圖編造答案。盡量使答案簡明扼要。總是在回答的最后說“謝謝你的提問!”。{context}問題: {question}有用的回答:"""QA_CHAIN_PROMPT = PromptTemplate(input_variables=["context","question"],template=template)# 運行 chainqa_chain = RetrievalQA.from_chain_type(llm,retriever=vectordb.as_retriever(),return_source_documents=True,chain_type_kwargs={"prompt":QA_CHAIN_PROMPT})return qa_chainclass Model_center():"""存儲檢索問答鏈的對象 """def __init__(self):# 構造函數,加載檢索問答鏈self.chain = load_chain()def qa_chain_self_answer(self, question: str, chat_history: list = []):"""調用問答鏈進行回答"""if question == None or len(question) < 1:return "", chat_historytry:chat_history.append((question, self.chain({"query": question})["result"]))# 將問答結果直接附加到問答歷史中,Gradio 會將其展示出來return "", chat_historyexcept Exception as e:return e, chat_historyimport gradio as gr# 實例化核心功能對象
model_center = Model_center()
# 創建一個 Web 界面
block = gr.Blocks()
with block as demo:with gr.Row(equal_height=True):   with gr.Column(scale=15):# 展示的頁面標題gr.Markdown("""<h1><center>InternLM</center></h1><center>書生浦語</center>""")with gr.Row():with gr.Column(scale=4):# 創建一個聊天機器人對象chatbot = gr.Chatbot(height=450, show_copy_button=True)# 創建一個文本框組件,用于輸入 prompt。msg = gr.Textbox(label="Prompt/問題")with gr.Row():# 創建提交按鈕。db_wo_his_btn = gr.Button("Chat")with gr.Row():# 創建一個清除按鈕,用于清除聊天機器人組件的內容。clear = gr.ClearButton(components=[chatbot], value="Clear console")# 設置按鈕的點擊事件。當點擊時,調用上面定義的 qa_chain_self_answer 函數,并傳入用戶的消息和聊天歷史記錄,然后更新文本框和聊天機器人組件。db_wo_his_btn.click(model_center.qa_chain_self_answer, inputs=[msg, chatbot], outputs=[msg, chatbot])gr.Markdown("""提醒:<br>1. 初始化數據庫時間可能較長,請耐心等待。2. 使用中如果出現異常,將會在文本輸入框進行展示,請不要驚慌。 <br>""")
gr.close_all()
# 直接啟動
demo.launch()

通過將上述代碼封裝為 run_gradio.py 腳本,直接通過 python 命令運行,即可在本地啟動知識庫助手的 Web Demo,默認會在 7860 端口運行,接下來將服務器端口映射到本地端口即可訪問:

運行效果

在這里插入圖片描述

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

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

相關文章

【大廠AI課學習筆記NO.53】2.3深度學習開發任務實例(6)數據采集

這個系列寫了53期了&#xff0c;很多朋友收藏&#xff0c;看來還是覺得有用。 后續我會把相關的內容&#xff0c;再次整理&#xff0c;做成一個人工智能專輯。 今天學習到了數據采集的環節。 這里有個問題&#xff0c;數據準備包括什么&#xff0c;還記得嗎&#xff1f; 數…

ZStack Cube超融合入選IDC《中國超融合基礎架構市場評估》報告

近日&#xff0c;IDC發布了《中國超融合基礎架構市場評估&#xff0c;2023》。IDC針對中國超融合基礎架構市場的發展現狀展開了調研&#xff0c;明確了最終用戶構建融合型云平臺的痛點和難點&#xff0c;闡述了市場中各技術服務提供商的服務方案和優勢&#xff0c;并對未來中國…

vue3+ts+vite數據大屏自適應總結(兩種方法)

總結一下我常用的數據大屏自適應方法 目錄 1、通過css縮放方案&#xff1a; 利用transform&#xff1a;scale 進行適配2、采用rem布局&#xff0c; 根據屏幕分辨率大小不同&#xff0c;調整根元素html的font-size&#xff0c; 從而達到每個元素寬高自動變化&#xff0c;適配不…

接口測試實戰--mock測試、日志模塊

一、mock測試 在前后端分離項目中,當后端工程師還沒有完成接口開發的時候,前端開發工程師利用Mock技術,自己用mock技術先調用一個虛擬的接口,模擬接口返回的數據,來完成前端頁面的開發。 接口測試和前端開發有一個共同點,就是都需要用到后端工程師提供的接口。所以,當…

Redis速學

一、介紹Redis 基本概念和特點 Redis是一個開源的內存數據庫&#xff0c;它主要用于數據緩存和持久化。其數據存儲在內存中&#xff0c;這使得它具有非常快的讀寫速度。Redis支持多種數據結構&#xff0c;包括字符串、哈希、列表、集合和有序集合&#xff0c;這使得它非常靈活…

書生·浦語大模型圖文對話Demo搭建

前言 本節我們先來搭建幾個Demo來感受一下書生浦語大模型 InternLM-Chat-7B 智能對話 Demo 我們將使用 InternStudio 中的 A100(1/4) 機器和 InternLM-Chat-7B 模型部署一個智能對話 Demo 環境準備 在 InternStudio 平臺中選擇 A100(1/4) 的配置&#xff0c;如下圖所示鏡像…

微店商品詳情 API 支持哪些商品信息的獲取?

微店&#xff08;Weidian&#xff09;并沒有一個公開的、官方維護的API文檔來供開發者使用。這意味著&#xff0c;如果你想要獲取微店商品詳情或其他相關信息&#xff0c;你通常需要通過微店官方提供的方式來實現&#xff0c;例如使用其開放平臺、官方SDK或聯系微店的技術支持獲…

Spring常見面試題知識點總結(三)

7. Spring MVC&#xff1a; MVC架構的概念。 MVC&#xff08;Model-View-Controller&#xff09;是一種軟件設計模式&#xff0c;旨在將應用程序分為三個主要組成部分&#xff0c;以實現更好的代碼組織、可維護性和可擴展性。每個組件有著不同的職責&#xff0c;相互之間解耦…

11.Prometheus常見PromeQL表達式

平凡也就兩個字: 懶和惰; 成功也就兩個字: 苦和勤; 優秀也就兩個字: 你和我。 跟著我從0學習JAVA、spring全家桶和linux運維等知識&#xff0c;帶你從懵懂少年走向人生巔峰&#xff0c;迎娶白富美&#xff01; 關注微信公眾號【 IT特靠譜 】&#xff0c;每天都會分享技術心得~ …

YOLO算法

YOLO介紹 YOLO&#xff0c;全稱為You Only Look Once: Unified, Real-Time Object Detection&#xff0c;是一種實時目標檢測算法。目標檢測是計算機視覺領域的一個重要任務&#xff0c;它不僅需要識別圖像中的物體類別&#xff0c;還需要確定它們的位置。與分類任務只關注對…

【矩陣】【方向】【素數】3044 出現頻率最高的素數

作者推薦 動態規劃的時間復雜度優化 本文涉及知識點 素數 矩陣 方向 LeetCode 3044 出現頻率最高的素數 給你一個大小為 m x n 、下標從 0 開始的二維矩陣 mat 。在每個單元格&#xff0c;你可以按以下方式生成數字&#xff1a; 最多有 8 條路徑可以選擇&#xff1a;東&am…

安裝 Ubuntu 22.04.3 和 docker

文章目錄 一、安裝 Ubuntu 22.04.31. 簡介2. 下載地址3. 系統安裝4. 系統配置 二、安裝 Docker1. 安裝 docker2. 安裝 docker compose3. 配置 docker 一、安裝 Ubuntu 22.04.3 1. 簡介 Ubuntu 22.04.3 是Linux操作系統的一個版本。LTS 版本支持周期到2032年。 系統要求雙核 C…

C++的模板template

一、什么是模板 C中的模板分為類模板和函數模板&#xff0c;并不是一個實際的類或函數&#xff0c;這指的是編譯器不會自動為其生成具體的可執行代碼。只有在具體執行時&#xff0c;編譯器才幫助其實例化。 二、為什么引入模板 拿我們最常見的交換函數來舉例子&#xff0c;如果…

代碼隨想錄 二叉樹第二周

目錄 101.對稱二叉樹 100.相同的樹 572.另一棵樹的子樹 104.二叉樹的最大深度 559.N叉樹的最大深度 111.二叉樹的最小深度 222.完全二叉樹的節點個數 110.平衡二叉樹 257.二叉樹的所有路徑 101.對稱二叉樹 101. 對稱二叉樹 已解答 簡單 相關標簽 相關企業 給你一…

《求生之路2》服務器如何選擇合適的內存和CPU核心數,以避免丟包和延遲高?

根據求生之路2服務器的實際案例分析選擇合適的內存和CPU核心數以避免丟包和延遲高的問題&#xff0c;首先需要考慮游戲的類型和對服務器配置的具體要求。《求生之路2》作為一款多人在線射擊游戲&#xff0c;其服務器和網絡優化對于玩家體驗至關重要。 首先&#xff0c;考慮到游…

Java應用程序注冊成Linux系統服務后,關閉Java應用程序打印系統日志

Java應用程序有自己的日志框架&#xff0c;有指定位置的日志文件&#xff0c;不需要在系統日志里記錄&#xff0c;占用磁盤空間。 1.Linux系統文件目錄 /etc/systemd/system/ 找到要修改的Java應用程序服務配置 比如bis-wz-80.service 2.設置不打印日志 StandardOutputnull S…

centos7 搭建 harbor 私有倉庫

一、下載安裝 1.1、harbor 可以直接從 github 上下載&#xff1a;Releases goharbor/harbor GitHub 這里選擇 v2.10.0 的版本 wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz 1.2、解壓 tar zxvf harbor-offlin…

L2 網絡 Mint Blockchain 正式對外發布測試網

Mint Blockchain 是由 NFTScan Labs 發起的聚焦在 NFT 生態的 L2 網絡&#xff0c;致力于促進 NFT 資產協議標準的創新和 NFT 在現實商業應用場景中的大規模采用。 Mint Blockchain 于 2024 年 2 月 28 號正式對外發布測試網&#xff0c;開始全面進入生態開發者測試開發階段。 …

2403C++,C++11玩轉無棧協程

原文 C11里也能玩無棧協程了? 答案是:可以! 事實上異網在很早時,C11里就可用無棧協程寫異步代碼了,只不過用起來不太方便,來看看C11里怎么用異網無棧協程寫一個回音服務器的吧. #包含 <異網.h> #包含 <內存> #包含 <向量> #包含 <異網/產生.h> 用 …

c++異常機制(5)-- 繼承與異常

我們在c異常機制(3)中自定義類型&#xff0c;我們將相應的異常封裝成了類&#xff0c;在類中實現一些方法&#xff0c;對異常進行處理。其中每一個類都實現了print()方法。 我們使用throw拋出相應異常的虛擬對象&#xff0c;在catch參數中進行匹配&#xff0c;但是如果有很多異…