原文地址:https://alphahinex.github.io/2023/05/14/paddlenlp-offline-use-community-model/
description: "修改源碼,或者修改模型名稱(chēng)為全路徑"
date: 2023.05.14 10:26
categories:
- AI
tags: [AI, PaddleNLP]
keywords: PaddlePaddle, PaddleNLP, NVIDIA, Salesforce CodeGen, GPU, offline
TL;DR
使用 PaddleNLP 加載社區(qū)模型時(shí),因?yàn)樯鐓^(qū)模型需聯(lián)網(wǎng)下載蝇刀,可先從在線環(huán)境進(jìn)行模型下載凭语,再將下載好的模型傳輸?shù)诫x線環(huán)境中蜒车。此時(shí)在離線環(huán)境下可能會(huì)遇到 https://github.com/PaddlePaddle/PaddleNLP/pull/5817 中描述的問(wèn)題潭袱,可參照該 PR files 中內(nèi)容修改摇零,以支持離線環(huán)境的正常使用磨确。
PaddleNLP
PaddleNLP是一款簡(jiǎn)單易用且功能強(qiáng)大的自然語(yǔ)言處理開(kāi)發(fā)庫(kù)沽甥。聚合業(yè)界優(yōu)質(zhì)預(yù)訓(xùn)練模型并提供開(kāi)箱即用的開(kāi)發(fā)體驗(yàn),覆蓋NLP多場(chǎng)景的模型庫(kù)搭配產(chǎn)業(yè)實(shí)踐范例可滿足開(kāi)發(fā)者靈活定制的需求乏奥。 —— https://github.com/PaddlePaddle/PaddleNLP
PaddleNLP 文檔地址:https://paddlenlp.readthedocs.io/zh/latest/index.html#
不過(guò)從實(shí)際使用下來(lái)的體驗(yàn)來(lái)看摆舟,文檔內(nèi)容對(duì)剛接觸 PaddleNLP 的人并不友好,需要自行摸索和補(bǔ)充了解的內(nèi)容較多邓了。
PaddleNLP
依賴 PaddlePaddle恨诱,PaddlePaddle
分為 paddlepaddle
和 paddlepaddle-gpu
兩個(gè)版本,想使用 GPU 進(jìn)行計(jì)算骗炉,需要安裝 paddlepaddle-gpu
照宝。使用 GPU 版本,還涉及到 顯卡驅(qū)動(dòng)句葵、CUDA Toolkit厕鹃、cuDNN、cuBLAS 等剂碴,各個(gè)組件之間版本繁雜把将,兼容性問(wèn)題較多,想構(gòu)建起一個(gè)可用的環(huán)境不是一件容易的事情忆矛。
推薦使用 Docker 環(huán)境上手體驗(yàn)察蹲,安裝 NVIDIA Container Toolkit 之后,根據(jù) CUDA 和 cuDNN 選擇對(duì)應(yīng)的鏡像版本洪碳,如:
docker run --name dev --runtime=nvidia -v $PWD:/mnt -p 8888:8888 -it paddlecloud/paddlenlp:develop-gpu-cuda11.2-cudnn8-e72fb9 /bin/bash
即便是官方提供的鏡像递览,里面的組件版本也可能存在兼容性問(wèn)題。上面 paddlecloud/paddlenlp:develop-gpu-cuda11.2-cudnn8-e72fb9
這個(gè)鏡像瞳腌,在引入 paddlenlp
中的 Taskflow
時(shí)绞铃,會(huì)拋出異常,需要在容器里把 paddlepaddle-gpu
從 2.3.0
升級(jí)到 2.4.2
嫂侍。
Salesforce CodeGen
Salesforce CodeGen 是一組開(kāi)放的儿捧、支持多回合交談式 AI 編程的大語(yǔ)言模型,包含多種尺寸和數(shù)據(jù)集挑宠,模型命名方式為:
codegen-{model-size}-{data}
model-size
有四個(gè)選項(xiàng):350M
菲盾、2B
、6B
,16B
各淀,代表每個(gè)模型的參數(shù)數(shù)量懒鉴;data
有三個(gè)選項(xiàng):nl
、multi
碎浇、mono
临谱。
-
nl
模型基于 The Pile —— 一個(gè) 825.18 GB 的英文語(yǔ)料庫(kù)初始化和訓(xùn)練而來(lái) -
multi
模型基于nl
模型初始化,再使用由多種編程語(yǔ)言組成的代碼語(yǔ)料庫(kù)訓(xùn)練 -
mono
模型基于multi
模型初始化奴璃,再使用 Python 代碼語(yǔ)料庫(kù)訓(xùn)練
關(guān)于各數(shù)據(jù)集的詳細(xì)信息悉默,可見(jiàn) CodeGen: An Open Large Language Model for Code with Multi-Turn Program Synthesis 。
PaddleNLP 加載 CodeGen 模型
Online
在線環(huán)境下苟穆,加載內(nèi)置的模型時(shí)抄课,會(huì)從預(yù)設(shè)的網(wǎng)址下載對(duì)應(yīng)文件到本地。忽略了加載模型相關(guān)日志輸出的雳旅,使用 CodeGen 模型通過(guò)提示詞補(bǔ)全后續(xù)代碼的示例代碼如下:
$ python3
>>> from paddlenlp import Taskflow
>>> codegen = Taskflow("code_generation", model="Salesforce/codegen-350M-mono",decode_strategy="greedy_search", repetition_penalty=1.0)
>>> print(codegen("def lengthOfLongestSubstring(self, s: str) -> int:"))
['\n if not s:\n return 0\n \n dic = {}\n max_len = 0\n \n for i in range(len(s)):\n if s[i] in dic:\n dic[s[i]] += 1\n if dic[s[i]] > max_len:\n max_len = dic[s[i]]\n else:\n dic[s[i]] = 1\n \n return max_len']
此時(shí)在本地 ~/.paddlenlp
路徑下跟磨,會(huì)下載好模型相關(guān)文件:
$ pwd
/root/.paddlenlp
$ tree
.
├── datasets
├── models
│ ├── Salesforce
│ │ └── codegen-350M-mono
│ │ ├── added_tokens.json
│ │ ├── config.json
│ │ ├── merges.txt
│ │ ├── model_config.json
│ │ ├── model_state.pdparams
│ │ ├── special_tokens_map.json
│ │ ├── tokenizer_config.json
│ │ └── vocab.json
│ └── embeddings
└── packages
Offline
然而遺憾的是,上面的代碼在離線環(huán)境無(wú)法直接使用攒盈,即使將模型相關(guān)文件全部傳輸?shù)诫x線環(huán)境相同路徑內(nèi)抵拘,使用 Taskflow("code_generation", model="Salesforce/codegen-350M-mono")
時(shí)也會(huì)得到無(wú)法連接 bj.bcebos.com
域名的報(bào)錯(cuò):
HTTPSConnectionPool(host='bj.bcebos.com', port=443): Max retries exceeded with url: /paddlenlp/models/community/Salesforce/codegen-350M-mono/config.json (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x140053a90>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known'))
完整的報(bào)錯(cuò)信息可見(jiàn) https://github.com/PaddlePaddle/PaddleNLP/pull/5817 。
報(bào)錯(cuò)原因
報(bào)相關(guān)錯(cuò)誤的原因是沦童,PaddleNLP 在加載社區(qū)模型(community/model-name
)時(shí)仑濒,會(huì)先去判斷對(duì)應(yīng)模型文件在社區(qū)網(wǎng)站( 默認(rèn)為:https://bj.bcebos.com/paddlenlp/models/community )是否存在,不論本地是否已經(jīng)下載過(guò)了該模型偷遗。
解決思路
解決的思路很簡(jiǎn)單墩瞳,在下載社區(qū)模型相關(guān)文件時(shí),首先檢查緩存路徑中是否已經(jīng)存在對(duì)應(yīng)文件氏豌,如存在則直接使用喉酌,不存在再通過(guò)網(wǎng)絡(luò)請(qǐng)求進(jìn)行獲取。
修改文件
可在錯(cuò)誤堆棧中獲取報(bào)錯(cuò)環(huán)境中需要修改的具體文件路徑泵喘,如:
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/paddlenlp/transformers/model_utils.py
需要修改的文件如下泪电,或參考 https://github.com/PaddlePaddle/PaddleNLP/pull/5817/files 。
paddlenlp/transformers/configuration_utils.py
_get_config_dict
方法 elif from_hf_hub:
后面再添加一個(gè) elif
:
elif os.path.isfile(os.path.join(cache_dir, CONFIG_NAME)):
resolved_config_file = os.path.join(cache_dir, CONFIG_NAME)
paddlenlp/transformers/model_utils.py
_resolve_model_file_path
方法 0. when it is local file
后面增加一個(gè) elif
條件:
elif os.path.isfile(os.path.join(cache_dir, cls.resource_files_names["model_state"])):
return os.path.join(cache_dir, cls.resource_files_names["model_state"])
paddlenlp/transformers/auto/modeling.py
_from_pretrained
方法 # Assuming from community-contributed pretrained models
部分調(diào)整:
# Assuming from community-contributed pretrained models
else:
+ cached_standard_config = os.path.join(cache_dir, cls.model_config_file)
+ cached_legacy_config = os.path.join(cache_dir, cls.legacy_model_config_file)
standard_community_url = "/".join(
[COMMUNITY_MODEL_PREFIX, pretrained_model_name_or_path, cls.model_config_file]
)
legacy_community_url = "/".join(
[COMMUNITY_MODEL_PREFIX, pretrained_model_name_or_path, cls.legacy_model_config_file]
)
try:
- if url_file_exists(standard_community_url):
+ if os.path.isfile(cached_standard_config):
+ resolved_vocab_file = cached_standard_config
+ elif url_file_exists(standard_community_url):
resolved_vocab_file = get_path_from_url_with_filelock(standard_community_url, cache_dir)
+ elif os.path.isfile(cached_legacy_config):
+ resolved_vocab_file = cached_legacy_config
elif url_file_exists(legacy_community_url):
效果驗(yàn)證
離線環(huán)境下可通過(guò)下列方式纪铺,驗(yàn)證加載已下載好的社區(qū)模型是否會(huì)報(bào)錯(cuò):
from paddlenlp import Taskflow
codegen = Taskflow("code_generation", model="Salesforce/codegen-350M-mono",decode_strategy="greedy_search", repetition_penalty=1.0)
from paddlenlp.transformers import CodeGenForCausalLM, CodeGenTokenizer
CodeGenTokenizer.from_pretrained("Salesforce/codegen-350M-mono")
CodeGenForCausalLM.from_pretrained("Salesforce/codegen-350M-mono", load_state_as_np=True)
from paddlenlp.transformers import AutoModel
AutoModel.from_pretrained("Salesforce/codegen-350M-mono")
全路徑加載離線模型
在不修改代碼的情況下相速,也可通過(guò)模型文件全路徑在離線環(huán)境加載模型,但涉及到在線環(huán)境和離線環(huán)境的代碼不一致鲜锚,可自行取舍:
from paddlenlp.transformers import AutoModel
AutoModel.from_pretrained("~/.paddlenlp/models/Salesforce/codegen-350M-mono")