利用华为云学习大模型

421 阅读12分钟

前言

前段时间一直准备期末考试,现在有时间更新大模型的文章啦!!!

开始操作

原文章链接【云驻共创】LangChain+ChatGLM3实现本地知识库,转华为云ModelArts,实现大模型AI应用开发-云社区-华为云 (huaweicloud.com)基于LangChain+ChatGLM3的本地知识库问答 (huaweicloud.com)
在进行学习之前需要注册华为云账号,并且需要进行实名认证

image.png
进入这个页面后我们点击那个红色的按钮即可“Run in ModelArts”
我们点击这个以后就会进入一个内置jupyter页面,我们等待他初始化,然后我们选择一个免费的环境

image.png

下载模型

我们选择这个规格后就可以开始进行操作了

import os
import moxing as mox

work_dir = '/home/ma-user/work'
obs_path = 'obs://dtse-models/tar-models/chatglm3-6b.tar'
ma_path = os.path.join(work_dir, 'chatglm3-6b.tar')
mox.file.copy(obs_path, ma_path)

mox.file.copy_parallel('obs://modelarts-labs-bj4-v2/case_zoo/langchain-ChatGLM/file/service','service')

首先我们解析这段代码
import os这个想必都不陌生,处理文件和目录的python标准库
然后这个moxing其实是华为云提供的一个库,用于在ModelArts环境中操作OBS对象存储服务
后面这个work_dir为本地工作目录的路径,obs_path是OBS存储文件的路径,ma_path是将文件从OBS复制到本地工作目录后的目标路径
然后这行代码mox.file.copy(obs_path, ma_path)obs_path 中的文件 chatglm3-6b.tar 复制到本地路径 ma_path
这行代码mox.file.copy_parallel('obs://modelarts-labs-bj4-v2/case_zoo/langchain-ChatGLM/file/service','service')将OBS中 obs://modelarts-labs-bj4-v2/case_zoo/langchain-ChatGLM/file/service 路径下的整个目录复制到本地目录 service
然后我们单击旁边那个运行的按钮即可

image.png

os.chdir(work_dir)
!pwd
!tar -xvf chatglm3-6b.tar

这个就是解压到对应目录

import os
import moxing as mox

obs_path = 'obs://dtse-models/tar-models/nltk_data.tar'
ma_path = os.path.join(work_dir, 'nltk_data.tar')
mox.file.copy(obs_path, ma_path)

mox.file.copy_parallel('obs://modelarts-labs-bj4-v2/case_zoo/langchain-ChatGLM/file/docs','/home/ma-user/work/docs')

然后我们下载nltk_data数据
nltk_data是一个非常重要的资源库,为Python的自然语言处理(NLP)提供了大量的数据支持。 这些数据资源对于执行各种NLP任务至关重要,包括文本分类、信息提取、机器翻译等
上面这些代码和前面我们具体操作的形式是一样的

os.chdir(work_dir)
!pwd
!tar -xvf nltk_data.tar

这里是将我们这个数据资源库进行解压 然后我们需要下载text2vec-large-chinese模型 这个模型我搜索了一下,ChatGPT给出的解释是这样的

image.png

import os
import moxing as mox

obs_path = 'obs://dtse-models/tar-models/text2vec-large-chinese.tar'
ma_path = os.path.join(work_dir, 'text2vec-large-chinese.tar')
mox.file.copy(obs_path, ma_path)

然后又是下载解压,这个操作很系统化

os.chdir(work_dir)
!pwd
!tar -xvf text2vec-large-chinese.tar

配置环境

因为我们依赖的是python3.10.10及以上的环境,所以我们应该先创建虚拟环境

!/home/ma-user/anaconda3/bin/conda create -n python-3.10.10 python=3.10.10 -y --override-channels --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
!/home/ma-user/anaconda3/envs/python-3.10.10/bin/pip install ipykernel

这段代码用于在华为云 ModelArts 环境中创建一个新的 Conda 虚拟环境并安装 ipykernel

  1. 创建 Conda 虚拟环境

    !/home/ma-user/anaconda3/bin/conda create -n python-3.10.10 python=3.10.10 -y --override-channels --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
    
    • 使用 Conda 创建一个名为 python-3.10.10 的虚拟环境,并指定 Python 版本为 3.10.10。
    • -n python-3.10.10 指定虚拟环境的名称。
    • python=3.10.10 指定要安装的 Python 版本。
    • -y 自动确认所有提示,不需要手动输入。
    • --override-channels 指定要覆盖默认的 Conda 渠道。
    • --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main 指定使用清华大学的 Anaconda 镜像源,加快下载速度。
  2. 安装 ipykernel

    !/home/ma-user/anaconda3/envs/python-3.10.10/bin/pip install ipykernel
    
    • 这行代码在新创建的 python-3.10.10 虚拟环境中使用 pip 安装 ipykernel 包。
    • ipykernel 是 Jupyter 的内核,使得 Jupyter Notebook 可以使用不同的 Python 环境。
    • /home/ma-user/anaconda3/envs/python-3.10.10/bin/pip 是指定新创建虚拟环境中的 pip 执行文件。
import json
import os

data = {
   "display_name": "python-3.10.10",
   "env": {
      "PATH": "/home/ma-user/anaconda3/envs/python-3.10.10/bin:/home/ma-user/anaconda3/envs/python-3.7.10/bin:/modelarts/authoring/notebook-conda/bin:/opt/conda/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/ma-user/modelarts/ma-cli/bin:/home/ma-user/modelarts/ma-cli/bin:/home/ma-user/anaconda3/envs/PyTorch-1.8/bin"
   },
   "language": "python",
   "argv": [
      "/home/ma-user/anaconda3/envs/python-3.10.10/bin/python",
      "-m",
      "ipykernel",
      "-f",
      "{connection_file}"
   ]
}

if not os.path.exists("/home/ma-user/anaconda3/share/jupyter/kernels/python-3.10.10/"):
    os.mkdir("/home/ma-user/anaconda3/share/jupyter/kernels/python-3.10.10/")

with open('/home/ma-user/anaconda3/share/jupyter/kernels/python-3.10.10/kernel.json', 'w') as f:
    json.dump(data, f, indent=4)

这段代码的目的是为新创建的 Python 3.10.10 虚拟环境配置一个 Jupyter kernel,使得 Jupyter Notebook 可以使用这个环境

  1. 定义 kernel 配置数据

    import json
    import os
    
    data = {
       "display_name": "python-3.10.10",
       "env": {
          "PATH": "/home/ma-user/anaconda3/envs/python-3.10.10/bin:/home/ma-user/anaconda3/envs/python-3.7.10/bin:/modelarts/authoring/notebook-conda/bin:/opt/conda/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/ma-user/modelarts/ma-cli/bin:/home/ma-user/modelarts/ma-cli/bin:/home/ma-user/anaconda3/envs/PyTorch-1.8/bin"
       },
       "language": "python",
       "argv": [
          "/home/ma-user/anaconda3/envs/python-3.10.10/bin/python",
          "-m",
          "ipykernel",
          "-f",
          "{connection_file}"
       ]
    }
    
    • 这里定义了一个 data 字典,包含 Jupyter kernel 的配置信息。
    • "display_name":在 Jupyter Notebook 中显示的内核名称。
    • "env":设置环境变量 PATH,包含新虚拟环境的路径及其他必要路径。
    • "language":指定内核语言为 Python。
    • "argv":启动内核的命令和参数,其中 {connection_file} 是 Jupyter 在运行时替换的占位符。
  2. 检查并创建目标目录

    if not os.path.exists("/home/ma-user/anaconda3/share/jupyter/kernels/python-3.10.10/"):
        os.mkdir("/home/ma-user/anaconda3/share/jupyter/kernels/python-3.10.10/")
    
    • 这段代码检查目录 /home/ma-user/anaconda3/share/jupyter/kernels/python-3.10.10/ 是否存在,如果不存在则创建它。这个目录用于存放新的 Jupyter kernel 配置。
  3. 写入 kernel 配置文件

    with open('/home/ma-user/anaconda3/share/jupyter/kernels/python-3.10.10/kernel.json', 'w') as f:
        json.dump(data, f, indent=4)
    
    • 这段代码将 data 字典写入到目标路径下的 kernel.json 文件中,格式化为 JSON 格式,并设置缩进为 4 个空格,使其易于阅读。
    • kernel.json 文件告诉 Jupyter 如何启动和使用这个新的 Python 3.10.10 环境。

运行以后我们就可以开始进行下一步操作
然后我们刷新这个界面

image.png
我们将这个python-3.7.10变成python-3.10.10

image.png

!pip install transformers==4.30.2
!pip install sentencepiece==0.1.99
!pip install torch==2.0.1 torchvision==0.15.2
!pip install markdown==3.4.3
!pip install faiss-gpu==1.7.2
!pip install langchain==0.0.329 -i https://pypi.tuna.tsinghua.edu.cn/simple
!pip install nltk==3.8.1 -i https://pypi.tuna.tsinghua.edu.cn/simple
!pip install unstructured==0.10.24 -i https://pypi.tuna.tsinghua.edu.cn/simple
!pip install sentence-transformers==2.2.2 -i https://pypi.tuna.tsinghua.edu.cn/simple

然后安装对应依赖库,当然因为这些库需要进行下载,所以运行时间会有一些些长
具体这些库我在下面写了,如果感兴趣看看就行,不感兴趣直接点旁边菜单栏跳过就行

解释

这些命令用于在当前的 Python 环境中安装指定版本的 Python 库,这些库主要用于自然语言处理(NLP)、深度学习和数据处理。

  1. Transformers

    !pip install transformers==4.30.2
    
    • transformers 是由 Hugging Face 提供的一个库,用于访问和使用预训练的 transformer 模型,如 BERT、GPT、T5 等。它支持多种语言模型,并提供了方便的 API 用于模型加载、训练和推理。
    • 版本 4.30.2 是特定的版本号,确保安装该版本以避免版本兼容性问题。
  2. SentencePiece

    !pip install sentencepiece==0.1.99
    
    • sentencepiece 是一个文本分词工具,可以用于无监督文本分词和子词单元(subword units)建模。它常用于处理多语言文本,以提高模型的表现。
    • 版本 0.1.99 是特定的版本号。
  3. PyTorch 和 Torchvision

    !pip install torch==2.0.1 torchvision==0.15.2
    
    • torch 是一个流行的开源深度学习框架,由 Facebook 的 AI 研究实验室开发。它提供了灵活的张量运算和自动微分工具。
    • torchvision 是 PyTorch 的一个附加库,提供了常用的计算机视觉数据集、模型和图像变换工具。
    • 版本 2.0.1 和 0.15.2 是特定的版本号。
  4. Markdown

    !pip install markdown==3.4.3
    
    • markdown 是一个用于解析和生成 Markdown 格式文本的库。Markdown 是一种轻量级的标记语言,常用于写作格式化文本。
    • 版本 3.4.3 是特定的版本号。
  5. Faiss-gpu

    !pip install faiss-gpu==1.7.2
    
    • faiss 是一个用于高效相似性搜索和聚类的库,由 Facebook 开发。faiss-gpu 版本支持 GPU 加速,可以显著提高大规模数据集的处理速度。
    • 版本 1.7.2 是特定的版本号。
  6. Langchain

    !pip install langchain==0.0.329 -i https://pypi.tuna.tsinghua.edu.cn/simple
    
    • langchain 是一个用于构建和部署基于自然语言的链式生成模型的库。它帮助开发者将多个 NLP 模型组合成一个工作流。
    • 版本 0.0.329 是特定的版本号。使用 -i 参数指定了清华大学的 PyPI 镜像源,加快安装速度。
  7. NLTK(Natural Language Toolkit)

    !pip install nltk==3.8.1 -i https://pypi.tuna.tsinghua.edu.cn/simple
    
    • nltk 是一个用于处理和分析人类语言数据的库,提供了丰富的文本处理工具和数据集,常用于 NLP 任务。
    • 版本 3.8.1 是特定的版本号。使用 -i 参数指定了清华大学的 PyPI 镜像源,加快安装速度。
  8. Unstructured

    !pip install unstructured==0.10.24 -i https://pypi.tuna.tsinghua.edu.cn/simple
    
    • unstructured 是一个用于处理非结构化数据的库,支持多种文本处理操作,如分词、词性标注、命名实体识别等。
    • 版本 0.10.24 是特定的版本号。使用 -i 参数指定了清华大学的 PyPI 镜像源,加快安装速度。
  9. Sentence-Transformers

    !pip install sentence-transformers==2.2.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
    
    • sentence-transformers 是一个用于生成句子和文本嵌入的库,基于 transformer 模型。它可以用于文本相似度计算、聚类和检索任务。
    • 版本 2.2.2 是特定的版本号。使用 -i 参数指定了清华大学的 PyPI 镜像源,加快安装速度。

代码开发

image.png 这里这个解释其实就提到了LangChain这个框架,这个框架学习很重要,后面我们会在写文章仔细讲讲

from langchain.chains import RetrievalQA
from langchain.prompts.prompt import PromptTemplate

from service.config import LangChainCFG
from service.chatglm_service import ChatGLMService
from service.knowledge_service import KnowledgeService

class LangChainApplication(object):
    #初始化,加载ChatGLM3模型和本地知识库
    def __init__(self, config):
        self.config = config
        self.llm_service = ChatGLMService()
        self.llm_service.load_model(model_name_or_path=self.config.llm_model_path)
        self.knowledge_service = KnowledgeService(config)

    #获取大语言模型返回的答案(基于本地知识库查询)
    def get_knowledge_based_answer(self, query,
                                   history_len=5,
                                   temperature=0.1,
                                   top_p=0.9,
                                   top_k=4,
                                   chat_history=[]):
        #定义查询的提示模板格式:
        prompt_template = """基于以下已知信息,简洁和专业的来回答用户的问题。
            如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息",不允许在答案中添加编造成分,答案请使用中文。
            已知内容:
            {context}
            问题:
            {question}
            """
        prompt = PromptTemplate(template=prompt_template,
                                input_variables=["context", "question"])
        self.llm_service.history = chat_history[-history_len:] if history_len > 0 else []

        self.llm_service.temperature = temperature
        self.llm_service.top_p = top_p

        #利用预先存在的语言模型(llm)、检索器(retriever)、提示(prompt)来创建并初始化BaseRetrievalQA类的实例
        knowledge_chain = RetrievalQA.from_llm(
            llm=self.llm_service,
            #基于本地知识库构建一个检索器,并仅返回top_k的结果
            retriever=self.knowledge_service.knowledge_base.as_retriever(
                search_kwargs={"k": top_k}),
            prompt=prompt)
        
        #combine_documents_chain的作用是将查询返回的文档内容(page_content)合并到一起作为prompt中context的值
        #将combine_documents_chain的合并文档内容改为{page_content}(代码默认定义为:Context:\n{page_content}),以适配中文
        knowledge_chain.combine_documents_chain.document_prompt = PromptTemplate(
            input_variables=["page_content"], template="{page_content}")
        
        #返回结果中是否包含源文档
        knowledge_chain.return_source_documents = True

        #传入问题内容进行查询
        result = knowledge_chain({"query": query})
        return result
    
    #获取大语言模型返回的答案(未基于本地知识库查询)
    def get_llm_answer(self, query):
        result = self.llm_service._call(query)
        return result

这段代码定义了一个 LangChainApplication 类,该类使用 LangChain 框架与 ChatGLM 模型进行交互,并利用本地知识库进行查询以提供基于知识的答案

类和方法解释

  1. LangChainApplication 类

    • 这个类主要用于初始化和使用大语言模型(ChatGLM3)以及本地知识库,以便提供基于知识库的回答和直接的大语言模型回答。
  2. __init__ 方法

    • 参数config 是配置对象。
    • 功能:初始化类实例时加载 ChatGLM3 模型和本地知识库。
    • 成员变量
      • self.config: 保存传入的配置对象。
      • self.llm_service: ChatGLM 模型服务实例。
      • self.knowledge_service: 知识库服务实例。
  3. get_knowledge_based_answer 方法

    • 参数
      • query: 用户查询的问题。
      • history_len: 保存的聊天历史记录的长度。
      • temperature: 生成文本的温度参数。
      • top_p: 生成文本的核采样参数。
      • top_k: 检索器返回的结果数量。
      • chat_history: 聊天历史记录。
    • 功能:根据用户查询的问题,利用本地知识库进行检索并生成回答。
    • 步骤
      • 定义提示模板,用于指导模型如何回答问题。
      • 设置 ChatGLM 模型的历史记录和生成文本的参数。
      • 利用本地知识库创建一个检索器,仅返回 top_k 个结果。
      • 定义如何将检索到的文档内容合并到提示中。
      • 设置是否在结果中返回源文档。
      • 执行查询并返回结果。
  4. get_llm_answer 方法

    • 参数query 是用户查询的问题。
    • 功能:直接调用大语言模型生成回答,不使用本地知识库。
    • 步骤:直接调用 ChatGLMService_call 方法生成回答并返回。

主要模块解释

  1. LangChain

    • LangChain 是一个框架,用于构建基于语言模型的应用程序,支持各种 NLP 任务。
  2. ChatGLMService

    • 假设这是一个自定义的服务类,用于加载和调用 ChatGLM3 模型。
  3. KnowledgeService

    • 假设这是一个自定义的服务类,用于加载和管理本地知识库。
  4. RetrievalQA

    • LangChain 中的一个类,用于创建基于检索的问答系统。
  5. PromptTemplate

    • 用于定义提示模板,以指导模型如何回答问题。

功能测试

from service.config import LangChainCFG

config = LangChainCFG()
application = LangChainApplication(config)
result = application.get_llm_answer('ModelBox是什么')
print('\nresult of llm:\n')
print(result)
print('\n########################################\n')

application.knowledge_service.init_knowledge_base()
result2 = application.get_knowledge_based_answer('ModelBox是什么')
print('\n########################################\n')
print('\nresult of knowledge base:\n')
print(result2)

在这里华为云给出了这个例子,我们点击运行后就可以看见对应的信息了

image.png 至此, 我们这篇文章的学习就完成了,我们可以发现这个其实和我们当时调用api那篇文章很像,但是又有一些不同的地方,我们这里是直接在我们计算机上面下载对应模型,然后进行操作

作业

image.png 这个是华为云上面提供的一道题,我们可以直接在jupyter上面直接进行书写
如果这篇文章可以帮助到您,可以点赞加收藏,你们的支持是我滴动力