diff --git a/.github/workflows/onnx.yml b/.github/workflows/onnx.yml new file mode 100644 index 00000000..acb5bec2 --- /dev/null +++ b/.github/workflows/onnx.yml @@ -0,0 +1,57 @@ +name: 'onnx docker' + +on: + workflow_dispatch: + push: + branches: ['master'] + paths: + - 'onnx/Dockerfile' + - 'onnx/export/**' + - 'onnx/misc/**' + - 'onnx/version.txt' + - '.github/workflow/onnx.yml' + pull_request: + branches: ['master'] + paths: + - 'onnx/Dockerfile' + - 'onnx/export/**' + - 'onnx/misc/**' + - 'onnx/version.txt' + - '.github/workflow/onnx.yml' + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Set Env + run: | + VERSION=$(cat onnx/version.txt) + echo "VERSION=$VERSION" >> $GITHUB_ENV + - + name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - + name: Build and push + uses: docker/build-push-action@v4 + with: + context: ./onnx/ + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{secrets.DOCKER_ORG}}/altclip-onnx:latest, ${{secrets.DOCKER_ORG}}/altclip-onnx:${{env.VERSION}} + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + GIT=https://github.com/${{github.repository}}.git diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 00000000..28b9ff63 --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +python 3.10.11 diff --git a/README_zh.md b/README_zh.md old mode 100755 new mode 100644 index 3a2f44c4..7d965523 --- a/README_zh.md +++ b/README_zh.md @@ -7,88 +7,82 @@ -------------------------------------------------------------------------------- - -**FlagAI飞智**是一个快速、易于使用和可扩展的大模型工具包。 我们的目标是支持在多模态的各种下游任务上训练、微调和部署大规模模型。 +**FlagAI 飞智**是一个快速、易于使用和可扩展的大模型工具包。 我们的目标是支持在多模态的各种下游任务上训练、微调和部署大规模模型。

## 为什么你需要 FlagAI? 1. **可通过 API 快速下载模型** - - 提供 API 方便你快速下载模型,并在给定(中/英文)文本上使用这些预训练模型,在从[SuperGLUE](https://super.gluebenchmark.com/)和[CLUE](https://github.com/CLUEbenchmark/CLUE) benchmarks收集的广泛使用的数据集上对它们进行微调。 - - FlagAI 现已支持 30+ 主流模型,包括语言模型[**Aquila**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/Aquila), 多模态模型 [**AltCLIP**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/AltCLIP) 、文生图模型 [**AltDiffusion**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/AltDiffusion) [![Huggingface space](https://img.shields.io/badge/🤗-Huggingface%20Space-cyan.svg)](https://huggingface.co/spaces/BAAI/bilingual_stable_diffusion)、最高百亿参数的 **[悟道GLM](/doc_zh/GLM.md)**,[**EVA-CLIP**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/EVA_CLIP)、**[Galactica](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/galactica)**、**OPT**、**BERT**、**RoBERTa**、**GPT2**、**T5**、**ALM**、**Huggingface Transformers** 等。 - -2. **仅用十行代码即可进行并行训练** - 飞智由四个最流行的数据/模型并行库([PyTorch](https://pytorch.org/)/[Deepspeed](https://www.deepspeed.ai/)/[Megatron-LM](https://github.com/NVIDIA/Megatron-LM)/[BMTrain](https://github.com/OpenBMB/BMTrain))提供支持,它们之间实现了无缝集成。 你可以用不到十行代码来并行你的训练/测试过程。 - -3. **提供提示学习工具包** + 提供 API 方便你快速下载模型,并在给定(中 / 英文)文本上使用这些预训练模型,在从[SuperGLUE](https://super.gluebenchmark.com/)和[CLUE](https://github.com/CLUEbenchmark/CLUE) benchmarks 收集的广泛使用的数据集上对它们进行微调。 - FlagAI 提供了提示学习([prompt-learning](https://github.com/FlagAI-Open/FlagAI/blob/master/docs/TUTORIAL_7_PROMPT_LEARNING.md))的工具包,用于少样本学习(few-shot learning)任务。 - -4. **尤其擅长中文任务** + FlagAI 现已支持 30+ 主流模型,包括语言模型[**Aquila**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/Aquila), 多模态模型 [**AltCLIP**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/AltCLIP) 、文生图模型 [**AltDiffusion**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/AltDiffusion) [![Huggingface space](https://img.shields.io/badge/🤗-Huggingface%20Space-cyan.svg)](https://huggingface.co/spaces/BAAI/bilingual_stable_diffusion)、最高百亿参数的 **[悟道 GLM](/doc_zh/GLM.md)**,[**EVA-CLIP**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/EVA_CLIP)、**[Galactica](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/galactica)**、**OPT**、**BERT**、**RoBERTa**、**GPT2**、**T5**、**ALM**、**Huggingface Transformers** 等。 - FlagAI 目前支持的模型可以应用于文本分类、信息提取、问答、摘要、文本生成等任务,尤其擅长中文任务。 +2. **仅用十行代码即可进行并行训练** + + 飞智由四个最流行的数据 / 模型并行库([PyTorch](https://pytorch.org/)/[Deepspeed](https://www.deepspeed.ai/)/[Megatron-LM](https://github.com/NVIDIA/Megatron-LM)/[BMTrain](https://github.com/OpenBMB/BMTrain))提供支持,它们之间实现了无缝集成。 你可以用不到十行代码来并行你的训练 / 测试过程。 + +3. **提供提示学习工具包** + + FlagAI 提供了提示学习([prompt-learning](https://github.com/FlagAI-Open/FlagAI/blob/master/docs/TUTORIAL_7_PROMPT_LEARNING.md))的工具包,用于少样本学习 (few-shot learning) 任务。 +4. **尤其擅长中文任务** + FlagAI 目前支持的模型可以应用于文本分类、信息提取、问答、摘要、文本生成等任务,尤其擅长中文任务。 ## 工具包及已支持的模型 > 本项目的部分代码基于 [GLM](https://github.com/THUDM/GLM),[Transformers](https://github.com/huggingface/transformers),[timm](https://github.com/rwightman/pytorch-image-models) 和 [DeepSpeedExamples](https://github.com/microsoft/DeepSpeedExamples/tree/master/Megatron-LM). - ### 工具 | 工具名称 | 描述 | 样例 | |:-------------- |:---------- |:------------------------------------------------------ | -| `GLM_custom_pvp` | 自定义 PET 模板 | [README.md](./examples/glm_custom_pvp/README.md) | +| `GLM_custom_pvp` | 自定义 PET 模板 | [README.md](./examples/glm_custom_pvp/README.md) | | `GLM_ptuning` | p-tuning 工具 | —— | | `BMInf-generate` | 推理加速 | [README.md](./examples/bminf_generate/README.md) | ### 模型 -| 模型名称 | 任务 | 训练 | 微调 | 推理 | 样例 | +| 模型名称 | 任务 | 训练 | 微调 | 推理 | 样例 | | :---------------- | :------- | :-- |:-- | :-- | :--------------------------------------------- | -| Aquila | 自然语言处理 | ✅ | ✅ | ✅ | [README.md](examples/Aquila/README.md) -| ALM | 阿拉伯语文本生成 | ✅ | ❌ | ✅ | [README.md](/examples/ALM/README.md) | -| AltCLIP | 文图匹配 | ✅ | ✅ | ✅ | [README.md](/examples/AltCLIP/README.md) | -| AltCLIP-m18 | 文图匹配 | ✅ | ✅ | ✅ | [README.md](examples/AltCLIP-m18/README.md) | +| Aquila | 自然语言处理 | ✅ | ✅ | ✅ | [README.md](examples/Aquila/README.md) +| ALM | 阿拉伯语文本生成 | ✅ | ❌ | ✅ | [README.md](/examples/ALM/README.md) | +| AltCLIP | 文图匹配 | ✅ | ✅ | ✅ | [README.md](/examples/AltCLIP/README.md) | +| AltCLIP-m18 | 文图匹配 | ✅ | ✅ | ✅ | [README.md](examples/AltCLIP-m18/README.md) | | AltDiffusion | 文生图 | ❌ | ❌ | ✅ | [README.md](/examples/AltDiffusion/README.md) | | AltDiffusion-m18 | 文生图,支持 18 种语言 | ❌ | ❌ | ✅ | [README.md](/examples/AltDiffusion-m18/README.md) | | BERT-title-generation-english | 英文标题生成 | ✅ | ❌ | ✅ | [README.md](/examples/bert_title_generation_english/README.md) | -| CLIP | 图文匹配 | ✅ | ❌ | ✅ | —— | -| CPM3-finetune | 文本续写 | ❌ | ✅ | ❌ | —— | -| CPM3-generate | 文本续写 | ❌ | ❌ | ✅ | —— | +| CLIP | 图文匹配 | ✅ | ❌ | ✅ | —— | +| CPM3-finetune | 文本续写 | ❌ | ✅ | ❌ | —— | +| CPM3-generate | 文本续写 | ❌ | ❌ | ✅ | —— | | CPM3_pretrain | 文本续写 | ✅ | ❌ | ❌ | —— | | CPM_1 | 文本续写 | ❌ | ❌ | ✅ | [README.md](/examples/cpm_1/README.md) | | EVA-CLIP | 图文匹配 | ✅ | ✅ | ✅ | [README.md](/examples/EVA_CLIP/README.md) | -| Galactica | 文本续写 | ❌ | ❌ | ✅ | —— | +| Galactica | 文本续写 | ❌ | ❌ | ✅ | —— | | GLM-large-ch-blank-filling | 完形填空问答 | ❌ | ❌ | ✅ | [TUTORIAL](/doc_zh/TUTORIAL_11_GLM_BLANK_FILLING_QA.md) | | GLM-large-ch-poetry-generation | 诗歌生成 | ✅ | ❌ | ✅ | [TUTORIAL](/doc_zh/TUTORIAL_13_GLM_EXAMPLE_PEOTRY_GENERATION.md) | | GLM-large-ch-title-generation | 标题生成 | ✅ | ❌ | ✅ | [TUTORIAL](/doc_zh/TUTORIAL_12_GLM_EXAMPLE_TITLE_GENERATION.md) | -| GLM-pretrain | 预训练 | ✅ | ❌ | ❌ | —— | -| GLM-seq2seq | 生成任务 | ✅ | ❌ | ✅ | —— | -| GLM-superglue | 判别任务 | ✅ | ❌ | ❌ | —— | +| GLM-pretrain | 预训练 | ✅ | ❌ | ❌ | —— | +| GLM-seq2seq | 生成任务 | ✅ | ❌ | ✅ | —— | +| GLM-superglue | 判别任务 | ✅ | ❌ | ❌ | —— | | GPT-2-text-writting | 文本续写 | ❌ | ❌ | ✅ | [TUTORIAL](/doc_zh/TUTORIAL_18_GPT2_WRITING.md) | -| GPT2-text-writting | 文本续写 | ❌ | ❌ | ✅ | —— | -| GPT2-title-generation | 标题生成 | ❌ | ❌ | ✅ | —— | -| OPT | 文本续写 | ❌ | ❌ | ✅ | [README.md](/examples/opt/README.md) | +| GPT2-text-writting | 文本续写 | ❌ | ❌ | ✅ | —— | +| GPT2-title-generation | 标题生成 | ❌ | ❌ | ✅ | —— | +| OPT | 文本续写 | ❌ | ❌ | ✅ | [README.md](/examples/opt/README.md) | | RoBERTa-base-ch-ner | 命名实体识别 | ✅ | ❌ | ✅ | [TUTORIAL](/doc_zh/TUTORIAL_17_BERT_EXAMPLE_NER.md) | | RoBERTa-base-ch-semantic-matching | 语义相似度匹配 | ✅ | ❌ | ✅ | [TUTORIAL](/doc_zh/TUTORIAL_16_BERT_EXAMPLE_SEMANTIC_MATCHING.md) | | RoBERTa-base-ch-title-generation | 标题生成 | ✅ | ❌ | ✅ | [TUTORIAL](/doc_zh/TUTORIAL_15_BERT_EXAMPLE_TITLE_GENERATION.md) | -| RoBERTa-faq | 问答 | ❌ | ❌ | ✅ | [README.md](/examples/roberta_faq/README.md) | -| Swinv1 | 图片分类 | ✅ | ❌ | ✅ | —— | -| Swinv2 | 图片分类 | ✅ | ❌ | ✅ | —— | +| RoBERTa-faq | 问答 | ❌ | ❌ | ✅ | [README.md](/examples/roberta_faq/README.md) | +| Swinv1 | 图片分类 | ✅ | ❌ | ✅ | —— | +| Swinv2 | 图片分类 | ✅ | ❌ | ✅ | —— | | T5-huggingface-11b | 训练 | ✅ | ❌ | ❌ | [TUTORIAL](/doc_zh/TUTORIAL_14_HUGGINGFACE_T5.md) | | T5-title-generation | 标题生成 | ❌ | ❌ | ✅ | [TUTORIAL](/doc_zh/TUTORIAL_19_T5_EXAMPLE_TITLE_GENERATION.md) | -| T5-flagai-11b | 预训练 | ✅ | ❌ | ❌ | —— | +| T5-flagai-11b | 预训练 | ✅ | ❌ | ❌ | —— | | ViT-cifar100 | 预训练 | ✅ | ❌ | ❌ | —— | - > 更多样例见 [./examples](https://github.com/FlagAI-Open/FlagAI/tree/master/examples) 目录,更多中文教程见 [./docs_zh](https://github.com/FlagAI-Open/FlagAI/tree/master/doc_zh) 目录。 - ## 贡献代码 感谢您对贡献的兴趣!请先阅读 [贡献者指南](CONTRIBUTING.md),然后从 [未解决的问题](https://github.com/FlagAI-Open/FlagAI/issues) 寻找你感兴趣的任务开启贡献之旅! @@ -98,34 +92,32 @@ 欢迎在 [GitHub Issues](https://github.com/FlagAI-Open/FlagAI/issues) 中提出你的问题,或在 [Discussions ](https://github.com/FlagAI-Open/FlagAI/discussions) 板块交流使用经验。 * 官方邮箱:open.platform@baai.ac.cn。 -* 知乎:[FlagAI飞智](https://www.zhihu.com/people/95-22-20-18) +* 知乎:[FlagAI 飞智](https://www.zhihu.com/people/95-22-20-18) * 扫码添加小助手加入**微信交流群**: - - ## Quick Start ### 安装环境 * Python 版本 >= 3.8 * PyTorch 版本 >= 1.8.0 -* [可选] 使用GPUs进行训练和测试, 你需要安装CUDA 和 NCCL +* [可选] 使用 GPUs 进行训练和测试 , 你需要安装 CUDA 和 NCCL -- 通过`pip`安装: +- 通过 `pip` 安装 : ```shell pip install -U flagai ``` -- [可选] 下载源码安装: +- [可选] 下载源码安装 : ```shell git clone https://github.com/FlagAI-Open/FlagAI.git python setup.py install ``` -- [可选] 开启训练加速需要安装 NVIDIA的 [apex](https://github.com/NVIDIA/apex) +- [可选] 开启训练加速需要安装 NVIDIA 的 [apex](https://github.com/NVIDIA/apex) ``` git clone https://github.com/NVIDIA/apex cd apex @@ -138,25 +130,25 @@ cd DeepSpeed DS_BUILD_CPU_ADAM=1 DS_BUILD_AIO=1 DS_BUILD_UTILS=1 pip install -e . ds_report # 检查deepspeed的状态 ``` -- [可选] 开启BMTrain训练,需要安装 [BMTrain](https://github.com/OpenBMB/BMTrain) ((>= 0.2.2)) +- [可选] 开启 BMTrain 训练,需要安装 [BMTrain](https://github.com/OpenBMB/BMTrain) ((>= 0.2.2)) ``` git clone https://github.com/OpenBMB/BMTrain cd BMTrain -python setup.py install +python setup.py install ``` -- [可选] 开启BMInf低资源推理, 需要安装[BMInf](https://github.com/OpenBMB/BMInf) +- [可选] 开启 BMInf 低资源推理 , 需要安装 [BMInf](https://github.com/OpenBMB/BMInf) ``` pip install bminf ``` -- [可选] 对于FlashAttention, 需要安装[Flash-attention](https://github.com/HazyResearch/flash-attention) (>=1.0.2) +- [可选] 对于 FlashAttention, 需要安装 [Flash-attention](https://github.com/HazyResearch/flash-attention) (>=1.0.2) ``` pip install flash-attn ``` - [可选] 镜像构建,请参照 [Dockerfile](https://github.com/FlagAI-Open/FlagAI/blob/master/Dockerfile) -- [提示] 单节点docker环境下,运行多卡数据并行需要设置host。 例如,docker节点 root@127.0.0.1,其端口 7110。 +- [提示] 单节点 docker 环境下,运行多卡数据并行需要设置 host。 例如,docker 节点 root@127.0.0.1,其端口 7110。 ``` >>> vim ~/.ssh/config Host 127.0.0.1 @@ -176,13 +168,13 @@ Host 127.0.0.1 from flagai.auto_model.auto_loader import AutoLoader auto_loader = AutoLoader( task_name="title-generation", - model_name="RoBERTa-base-ch" + model_name="RoBERTa-base-ch" ) model = auto_loader.get_model() tokenizer = auto_loader.get_tokenizer() ``` -这个例子是针对`title-generation`(文本摘要)任务的,你也可以通过修改`task_name`来为其他任务建模。 然后您可以使用模型和标记器进行微调或测试。 +这个例子是针对 `title-generation`(文本摘要)任务的,你也可以通过修改 `task_name` 来为其他任务建模。 然后您可以使用模型和标记器进行微调或测试。 ### 使用预测器 我们提供 `Predictor` 类来预测不同的任务,例如: @@ -202,8 +194,7 @@ for text in test_data: beam_size=3)) ``` -这个例子是针对 `seq2seq` 任务的,我们可以通过调用`predict_generate_beamsearch`函数得到`beam-search`结果。此外,我们还支持`NER`和`title generate`等任务的预测。 - +这个例子是针对 `seq2seq` 任务的,我们可以通过调用 `predict_generate_beamsearch` 函数得到 `beam-search` 结果。此外,我们还支持 `NER` 和 `title generate` 等任务的预测。 ### 命名实体识别任务示例 @@ -244,7 +235,6 @@ for t in test_data: print(f"result is {result}") ``` - ### 语义相似度匹配任务示例 ```python @@ -270,24 +260,26 @@ for text_pair in test_data: ``` +### 模型部署 -## 动态 -- [9 June 2023] 支持 v1.7.0版本, 增加Aquila [#324](https://github.com/FlagAI-Open/FlagAI/pull/324); -- [31 Mar 2023] 支持v1.6.3版本, 增加AltCLIP-m18模型 [#303](https://github.com/FlagAI-Open/FlagAI/pull/303) 以及 AltDiffusion-m18模型 [#302](https://github.com/FlagAI-Open/FlagAI/pull/302); -- [17 Mar 2023] 支持v1.6.2版本, 可以使用新的优化器 [#266](https://github.com/FlagAI-Open/FlagAI/pull/266), 并增加了英文gpt模型GPT2-base-en; -- [2 Mar 2023] 支持v1.6.1版本, 增加Galactica模型 [#234](https://github.com/FlagAI-Open/FlagAI/pull/234), 大模型推理的低资源工具包BMInf [#238](https://github.com/FlagAI-Open/FlagAI/pull/238), 以及P-tuning样例 [#227](https://github.com/FlagAI-Open/FlagAI/pull/238) -- [12 Jan 2023] 发布v1.6.0版本, 新增支持并行训练库 [**BMTrain**](https://github.com/OpenBMB/BMTrain) 以及集成 [**Flash Attention**](https://github.com/HazyResearch/flash-attention) 到 Bert 和 Vit 模型提速端到端训练, 示例见 [FlashAttentionBERT](https://github.com/FlagAI-Open/FlagAI/blob/master/examples/bert_title_generation_english/train_flash_atten.py)和 [FlashAttentionViT](https://github.com/FlagAI-Open/FlagAI/blob/master/examples/vit_cifar100/train_single_gpu_flash_atten.py). 同时增加了基于对比搜索的文本生成方法 [**SimCTG**](https://github.com/yxuansu/SimCTG) 以及基于 AltDiffusion 进行 DreamBooth 个性化微调, 示例见 [AltDiffusionNaruto](https://github.com/FlagAI-Open/FlagAI/blob/master/examples/AltDiffusion/dreambooth.py). -- [28 Nov 2022] 发布v1.5.0版本, 支持1.1B参数的 [**EVA-CLIP**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/EVA_CLIP) 以及[ALM: 基于GLM的阿拉伯语大模型], 示例见[**ALM**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/ALM) -- [10 Nov 2022] 发布v1.4.0版本, 支持[AltCLIP: 更改CLIP中的语言编码器以扩展语言功能](https://arxiv.org/abs/2211.06679v1), 示例见[**AltCLIP**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/AltCLIP)以及[**AltDiffusion**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/AltDiffusion) -- [29 Aug 2022] 支持v1.3.0版本, 增加CLIP模块以及重新设计了tokenizer的API: [#81](https://github.com/FlagAI-Open/FlagAI/pull/81) -- [21 Jul 2022] 支持v1.2.0版本, 支持ViT系列模型: [#71](https://github.com/FlagAI-Open/FlagAI/pull/71) -- [29 Jun 2022] 支持v1.1.0版本, 支持OPT的加载,微调和推理[#63](https://github.com/FlagAI-Open/FlagAI/pull/63) -- [17 May 2022] 做出了我们的第一份贡献[#1](https://github.com/FlagAI-Open/FlagAI/pull/1) +* AltCLIP 部署见 [AltCLIP 的 ONNX 模型导出](./onnx/README.md) -## 许可 LICENSE - - -FlagAI飞智大部分项目基于 [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0),但是请注意部分项目代码基于其他协议: +## 动态 +- [9 June 2023] 支持 v1.7.0 版本 , 增加 Aquila [#324](https://github.com/FlagAI-Open/FlagAI/pull/324); +- [31 Mar 2023] 支持 v1.6.3 版本 , 增加 AltCLIP-m18 模型 [#303](https://github.com/FlagAI-Open/FlagAI/pull/303) 以及 AltDiffusion-m18 模型 [#302](https://github.com/FlagAI-Open/FlagAI/pull/302); +- [17 Mar 2023] 支持 v1.6.2 版本 , 可以使用新的优化器 [#266](https://github.com/FlagAI-Open/FlagAI/pull/266), 并增加了英文 gpt 模型 GPT2-base-en; +- [2 Mar 2023] 支持 v1.6.1 版本 , 增加 Galactica 模型 [#234](https://github.com/FlagAI-Open/FlagAI/pull/234), 大模型推理的低资源工具包 BMInf [#238](https://github.com/FlagAI-Open/FlagAI/pull/238), 以及 P-tuning 样例 [#227](https://github.com/FlagAI-Open/FlagAI/pull/238) +- [12 Jan 2023] 发布 v1.6.0 版本 , 新增支持并行训练库 [**BMTrain**](https://github.com/OpenBMB/BMTrain) 以及集成 [**Flash Attention**](https://github.com/HazyResearch/flash-attention) 到 Bert 和 Vit 模型提速端到端训练 , 示例见 [FlashAttentionBERT](https://github.com/FlagAI-Open/FlagAI/blob/master/examples/bert_title_generation_english/train_flash_atten.py) 和 [FlashAttentionViT](https://github.com/FlagAI-Open/FlagAI/blob/master/examples/vit_cifar100/train_single_gpu_flash_atten.py). 同时增加了基于对比搜索的文本生成方法 [**SimCTG**](https://github.com/yxuansu/SimCTG) 以及基于 AltDiffusion 进行 DreamBooth 个性化微调 , 示例见 [AltDiffusionNaruto](https://github.com/FlagAI-Open/FlagAI/blob/master/examples/AltDiffusion/dreambooth.py). +- [28 Nov 2022] 发布 v1.5.0 版本 , 支持 1.1B 参数的 [**EVA-CLIP**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/EVA_CLIP) 以及 [ALM: 基于 GLM 的阿拉伯语大模型], 示例见 [**ALM**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/ALM) +- [10 Nov 2022] 发布 v1.4.0 版本 , 支持 [AltCLIP: 更改 CLIP 中的语言编码器以扩展语言功能](https://arxiv.org/abs/2211.06679v1), 示例见 [**AltCLIP**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/AltCLIP) 以及 [**AltDiffusion**](https://github.com/FlagAI-Open/FlagAI/tree/master/examples/AltDiffusion) +- [29 Aug 2022] 支持 v1.3.0 版本 , 增加 CLIP 模块以及重新设计了 tokenizer 的 API: [#81](https://github.com/FlagAI-Open/FlagAI/pull/81) +- [21 Jul 2022] 支持 v1.2.0 版本 , 支持 ViT 系列模型 : [#71](https://github.com/FlagAI-Open/FlagAI/pull/71) +- [29 Jun 2022] 支持 v1.1.0 版本 , 支持 OPT 的加载,微调和推理 [#63](https://github.com/FlagAI-Open/FlagAI/pull/63) +- [17 May 2022] 做出了我们的第一份贡献 [#1](https://github.com/FlagAI-Open/FlagAI/pull/1) + +## 许可 LICENSE + +FlagAI 飞智大部分项目基于 [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0),但是请注意部分项目代码基于其他协议: * Megatron-LM 是基于协议 [Megatron-LM license](https://github.com/NVIDIA/Megatron-LM/blob/main/LICENSE) * GLM 是基于协议 [MIT license](https://github.com/THUDM/GLM/blob/main/LICENSE) @@ -295,11 +287,10 @@ FlagAI飞智大部分项目基于 [Apache 2.0 license](https://www.apache.org/li ## 平台支持 -
+
- ## Misc ### ↳ Stargazers, thank you for your support! diff --git a/onnx/.envrc b/onnx/.envrc new file mode 100644 index 00000000..9a427020 --- /dev/null +++ b/onnx/.envrc @@ -0,0 +1,8 @@ +export PYTHONPATH=`pwd`:$PYTHONPATH + +if [ -f ".env" ]; then + set -o allexport + source .env + set +o allexport +fi + diff --git a/onnx/.gitignore b/onnx/.gitignore new file mode 100644 index 00000000..acbd3db9 --- /dev/null +++ b/onnx/.gitignore @@ -0,0 +1,9 @@ +.env +.DS_Store +__pycache__/ + +/onnx/* +!onnx/.keep + +dist/ +model/ diff --git a/onnx/.tool-versions b/onnx/.tool-versions new file mode 100644 index 00000000..28b9ff63 --- /dev/null +++ b/onnx/.tool-versions @@ -0,0 +1 @@ +python 3.10.11 diff --git a/onnx/Dockerfile b/onnx/Dockerfile new file mode 100755 index 00000000..4cd73bf3 --- /dev/null +++ b/onnx/Dockerfile @@ -0,0 +1,44 @@ +FROM ubuntu:23.10 + +WORKDIR app + +ADD ./version.txt version + +RUN sed -i s/ports.ubuntu.com/mirrors.aliyun.com/g /etc/apt/sources.list &&\ +sed -i s/archive.ubuntu.com/mirrors.aliyun.com/g /etc/apt/sources.list &&\ +sed -i s/security.ubuntu.com/mirrors.aliyun.com/g /etc/apt/sources.list &&\ +apt-get update && \ +apt-get install -y git pkg-config bash python3-full python3-pip python3-aiohttp &&\ +update-alternatives --install /usr/bin/python python /usr/bin/python3.11 1 &&\ +pip install -i https://mirrors.aliyun.com/pypi/simple/ \ + --break-system-packages \ + setuptools==66.0.0 \ + urllib3==1.26.16 \ + scipy transformers huggingface_hub packaging \ + tqdm requests cython \ + torch onnx && apt-get clean -y + +ARG GIT +ENV GIT=$GIT + +RUN git clone --depth=1 $GIT + +ADD os/ / + +RUN pip install -i https://mirrors.aliyun.com/pypi/simple/ PyYAML scikit-learn Pillow + +RUN cd FlagAI &&\ + sed -i '/PyYAML/d' setup.py &&\ + sed -i '/scikit-learn/d' setup.py &&\ + sed -i '/Pillow/d' setup.py &&\ + rm setup.cfg &&\ + python setup.py install + +RUN pip uninstall -y google-auth + +RUN \ + pip uninstall -y protobuf &&\ + pip install -i https://mirrors.aliyun.com/pypi/simple/ protobuf + +RUN pip install -i https://mirrors.aliyun.com/pypi/simple/ onnx +ENV PYTHONPATH /app diff --git a/onnx/README.md b/onnx/README.md new file mode 100644 index 00000000..64f5863e --- /dev/null +++ b/onnx/README.md @@ -0,0 +1,120 @@ +# AltCLIP 的 ONNX 模型导出 + +## ONNX 是什么? + +ONNX(Open Neural Network Exchange),开放神经网络交换,用于在各种深度学习训练和推理框架转换的一个中间表示格式。 + +在实际业务中,可以使用 Pytorch 或者 TensorFlow 训练模型,导出成 ONNX 格式,然后用 ONNX Runtime 直接运行 ONNX。 + +使用 ONNX 可以减少模型的依赖,降低部署成本。 + +也可以进一步借助 ONNX 转换成目标设备上运行时支撑的模型格式,比如 [TensorRT Engine](https://developer.nvidia.com/tensorrt)、[NCNN](https://github.com/Tencent/ncnn)、[MNN](https://github.com/alibaba/MNN) 等格式, 优化性能。 + +## 下载 AltCLIP 的 ONNX + +可以从[xxai/AltCLIP](https://huggingface.co/xxai/AltCLIP/tree/main)下载打包好的 onnx,并解压到 `FlagAI/onnx/onnx/` 下。 + +如此就可以直接运行 onnx 的测试,而无需下载原始模型运行导出。 + +## 文件说明 + +因为 flagai 的依赖复杂,所以构建容器便于导出。 + +### 脚本 + +* `./build.sh` 在本地构建容器 + + 可设置环境变量 `ORG=xxai` 使用 [hub.docker.com 上的已构建的镜像](https://hub.docker.com/repository/docker/xxai/altclip-onnx)。 + + 比如,运行 `ORG=xxai ./bash.sh` 。 + +* `./bash.sh` 在本地进入容器的 bash,方便调试 + +* `./export.sh` 运行容器,下载 pytorch 模型,然后转换为 onnx + + 设置环境变量 MODEL ,可以配置导出、测试脚本运行的模型 。 + + 默认导出的模型是 AltCLIP-XLMR-L-m18 ,还支持以下模型: + + * AltCLIP-XLMR-L + * AltCLIP-XLMR-L-m9 + + 运行后将生成 2 个 onnx 文件和很多权重文件 + + * onnx/AltCLIP-XLMR-L-m18/onnx/Img.onnx + * onnx/AltCLIP-XLMR-L-m18/onnx/Txt.onnx + + 具体用见下文的 onnx 模型的测试脚本。 + +* `./dist.sh` 运行容器,导出以上 3 个模型的 onnx,并打包放到 dist 目录下。 + +### 目录 + +* `model/` 存放下载的模型 +* `onnx/` 存放导出的 onnx,下载的 onnx 也请解压到这里 + +### 测试 + +#### onnx 模型的依赖安装 + +test/onnx 下面的依赖很简单,只有 transformers 和 onnxruntime,不依赖于 flagai。 + +onnxruntime 有很多版本可以选择,见[onnxruntime](https://onnxruntime.ai/)。 + +对于 python 而言,常见的运行时推荐如下: + +* 显卡 `pip install onnxruntime-gpu` +* ARM 架构的 MAC `pip install onnxruntime-silicon` (目前还不支持 python3.11) +* INTEL 的 CPU `pip install onnxruntime-openvino` +* 其他 CPU `pip install onnxruntime` + +运行 [./test/onnx/setup.sh](./test/onnx/setup.sh) 会自动判断环境,选择安装合适的 onnxruntime 版本和 transformers。 + +#### onnx 模型的测试脚本 + +请先安装 [direnv](https://github.com/direnv/direnv/blob/master/README.md) 并在本目录下 `direnv allow` 或者手工 `source .envrc` 来设置 PYTHONPATH 环境变量。 + +* [./test/onnx/onnx_img.py](./test/onnx/onnx_img.py) 生成图片向量 (norm 代表归一化的向量,可用于向量搜索) +* [./test/onnx/onnx_txt.py](./test/onnx/onnx_txt.py) 生成文本向量 +* [./test/onnx/onnx_test.py](./test/onnx/onnx_test.py) + + 匹配图片向量和文本向量,进行零样本分类 + + 可借助向量数据库,提升零样本分类的准确性,参见[ECCV 2022 | 无需下游训练,Tip-Adapter 大幅提升 CLIP 图像分类准确率](https://cloud.tencent.com/developer/article/2126102)。 +* [./test/onnx/onnx_load.py](./test/onnx/onnx_load.py) + + onnx 模型的加载代码,运行它可以看到当前机器可用的 onnx provider。 + + 比如苹果 M2 芯片的笔记本上运行如下: + + ``` + ❯ ./onnx_load.py 2>/dev/null + all providers : + ['TensorrtExecutionProvider', 'CUDAExecutionProvider', 'MIGraphXExecutionProvider', 'ROCMExecutionProvider', 'OpenVINOExecutionProvider', 'DnnlExecutionProvider', 'TvmExecutionProvider', 'VitisAIExecutionProvider', 'NnapiExecutionProvider', 'CoreMLExecutionProvider', 'ArmNNExecutionProvider', 'ACLExecutionProvider', 'DmlExecutionProvider', 'RknpuExecutionProvider', 'XnnpackExecutionProvider', 'CANNExecutionProvider', 'CPUExecutionProvider'] + + now can use providers : + ['CoreMLExecutionProvider', 'CPUExecutionProvider'] + ``` + + 可以创建 FlagAI/onnx/.env ,设置环境变量 `ONNX_PROVIDER`,配置当前环境的 Onnx Execution Provider,方便测试对比性能。 + + 设置的示例如下: + + ``` + ❯ cat FlagAI/onnx/.env + ONNX_PROVIDER=CoreMLExecutionProvider + ``` + + 设置成功后,需要在 `FlagAI/onnx` 目录下运行 `direnv allow` 或者手工 `source .envrc` 让其在当前命令行中生效。 + +#### pytorch 模型 + +用于对比 onnx 模型的向量输出,查看是否一致。 + +因为用到了 flagai,请如下图所示运行 [./bash.sh ](./bash.sh) 进入容器运行调试。 + +![](https://pub-b8db533c86124200a9d799bf3ba88099.r2.dev/2023/06/ei64CNo.webp) + +* [./test/clip/clip_img.py](./test/clip/clip_img.py) 生成图片向量 +* [./test/clip/clip_txt.py](./test/clip/clip_txt.py) 生成文本向量 +* [./test/clip/clip_test.py](./test/clip/clip_test.py) 匹配图片向量和文本向量,进行零样本分类 diff --git a/onnx/bash.sh b/onnx/bash.sh new file mode 100755 index 00000000..bb0654fa --- /dev/null +++ b/onnx/bash.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +DIR=$(realpath $0) && DIR=${DIR%/*} +cd $DIR +set -ex +mkdir -p out dist model + +NAME=altclip-onnx + +if ! [ -z $ORG ]; then + NAME=$ORG/$NAME +fi + +if [ -z "$1" ]; then + exe="exec bash" + it="-it" +else + exe="exec bash -c \"$@\"" + it="" +fi + +docker run \ + -v $DIR/misc:/app/misc \ + -v $DIR/img:/app/img \ + -v $DIR/export:/app/export \ + -v $DIR/onnx:/app/onnx \ + -v $DIR/dist:/app/dist \ + -v $DIR/model:/app/model \ + -v $DIR/test:/app/test \ + $it --rm $NAME bash -c "$exe" diff --git a/onnx/build.sh b/onnx/build.sh new file mode 100755 index 00000000..ae7bc70c --- /dev/null +++ b/onnx/build.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +DIR=$(realpath $0) && DIR=${DIR%/*} +cd $DIR +set -ex + +GIT=$(cat ../.git/config | grep url | awk -F= '{print $2}' | sed -e 's/[ ]*//g') + +# 替换 : 为 / +GIT=${GIT//://} + +# 替换 git@ 为 https:// +GIT=${GIT//git@/https:\/\/} + +docker build --build-arg GIT=$GIT . -t altclip-onnx diff --git a/onnx/dist.sh b/onnx/dist.sh new file mode 100755 index 00000000..5d99c6ba --- /dev/null +++ b/onnx/dist.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +DIR=$(realpath $0) && DIR=${DIR%/*} +cd $DIR +set -ex + +LI="L L-m9 L-m18" + +VERSION=$(cat version.txt) + +mkdir -p dist + +for model in $LI; do + export MODEL="AltCLIP-XLMR-${model}" + ./export.sh + ./export/tar.bz2.py + mv onnx/$MODEL.tar.bz2 dist/$MODEL-$VERSION.tar.bz2 +done diff --git a/onnx/export.sh b/onnx/export.sh new file mode 100755 index 00000000..4470d614 --- /dev/null +++ b/onnx/export.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +DIR=$(realpath $0) && DIR=${DIR%/*} +cd $DIR +set -ex + +cmd="export MODEL=$MODEL;export/onnx.sh" + +if ! [ -z $1 ]; then + cmd="$cmd && $@" +fi + +./bash.sh $cmd diff --git a/onnx/export/down.py b/onnx/export/down.py new file mode 100755 index 00000000..e1f721a2 --- /dev/null +++ b/onnx/export/down.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python + +from misc.config import MODEL_NAME, MODEL_DIR +from flagai.auto_model.auto_loader import AutoLoader + +loader = AutoLoader(task_name="txt_img_matching", + model_name=MODEL_NAME, + model_dir=MODEL_DIR) + +loader.get_model() diff --git a/onnx/export/onnx.sh b/onnx/export/onnx.sh new file mode 100755 index 00000000..d5f08f9a --- /dev/null +++ b/onnx/export/onnx.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +DIR=$(realpath $0) && DIR=${DIR%/*} +cd $DIR +set -ex + +./down.py +./onnx_export_processor.py +./onnx_export.py diff --git a/onnx/export/onnx_export.py b/onnx/export/onnx_export.py new file mode 100755 index 00000000..7ac00b34 --- /dev/null +++ b/onnx/export/onnx_export.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +from PIL import Image +from os import makedirs +from os.path import join +from misc.clip_model import TXT, IMG, TXT_NORM, IMG_NORM +from misc.config import ONNX_FP, opset_version, IMG_DIR +from misc.proc import transform, tokenizer +import torch + +makedirs(ONNX_FP, exist_ok=True) + +JPG = join(IMG_DIR, 'cat.jpg') + +image = Image.open(JPG) +image = transform(image) +image = torch.tensor(image) + + +def onnx_export(model, args, **kwds): + name = f'{model.__class__.__name__}.onnx' + fp = join(ONNX_FP, name) + torch.onnx.export( + model, + args, + fp, + export_params=True, + # verbose=True, + opset_version=opset_version, + do_constant_folding=False, + output_names=['output'], + **kwds) + print(name, "DONE\n") + # rename(fp, join(ONNX_DIR, name)) + + +# 参考 https://github.com/OFA-Sys/Chinese-CLIP/blob/master/cn_clip/deploy/pytorch_to_onnx.py +def export(txt, img): + onnx_export(txt, + tokenizer(['a photo of cat', 'a image of cat'], ), + input_names=['input', 'attention_mask'], + dynamic_axes={ + 'input': { + 0: 'batch', + 1: 'batch', + }, + 'attention_mask': { + 0: 'batch', + 1: 'batch', + } + }) + + onnx_export(img, + image, + input_names=['input'], + dynamic_axes={'input': { + 0: 'batch' + }}) + + +export(TXT, IMG) +export(TXT_NORM, IMG_NORM) diff --git a/onnx/export/onnx_export_processor.py b/onnx/export/onnx_export_processor.py new file mode 100755 index 00000000..a1bc8640 --- /dev/null +++ b/onnx/export/onnx_export_processor.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +from flagai.model.mm.AltCLIP import AltCLIPProcess +from misc.config import MODEL_FP, PROCESS_DIR +from os import makedirs + +makedirs(PROCESS_DIR, exist_ok=True) +proc = AltCLIPProcess.from_pretrained(MODEL_FP) +proc.save_pretrained(PROCESS_DIR) diff --git a/onnx/export/tar.bz2.py b/onnx/export/tar.bz2.py new file mode 100755 index 00000000..73c3cbcf --- /dev/null +++ b/onnx/export/tar.bz2.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +from misc.config import ONNX_DIR +from os.path import basename +import bz2 +import tarfile + + +def txz(src, to): + stream = bz2.BZ2File(to, 'w') + + with tarfile.TarFile(fileobj=stream, mode='w') as tar: + tar.add(src, arcname=basename(src)) + + stream.close() + + +txz(ONNX_DIR, ONNX_DIR + '.tar.bz2') diff --git a/onnx/github.action.md b/onnx/github.action.md new file mode 100644 index 00000000..3c8512e5 --- /dev/null +++ b/onnx/github.action.md @@ -0,0 +1,16 @@ +# github action 上的容器自动构建 + +在 github action 中配置秘钥,就可以实现自动构建推送容器 + +* DOCKER_ORG + 组织名 + +* DOCKER_USERNAME + hub.docker.com 登录的用户 + +* DOCKER_PASSWORD + hub.docker.com 登录的密码 + +详情见[../.github/workflows/onnx.yml](../.github/workflows/onnx.yml)。 + +修改 [./version.txt](./version.txt) 可以设置推送容器的版本号。 diff --git a/onnx/misc/__init__.py b/onnx/misc/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/onnx/misc/clip_model.py b/onnx/misc/clip_model.py new file mode 100755 index 00000000..a4dce5dd --- /dev/null +++ b/onnx/misc/clip_model.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +import torch +import torch.nn as nn +from .device import DEVICE +from .config import MODEL_FP +from flagai.model.mm.AltCLIP import CLIPHF +from misc.norm import norm + +MODEL = CLIPHF.from_pretrained(MODEL_FP) + +MODEL.eval() +MODEL.to(DEVICE) + + +class Img(nn.Module): + + def __init__(self): + super(Img, self).__init__() + self.model = MODEL + + def forward(self, image): + with torch.no_grad(): + image = image.to(DEVICE) + return self.model.get_image_features(image) + + +class ImgNorm(Img): + + def forward(self, image): + return norm(super(ImgNorm, self).forward(image)) + + +class Txt(nn.Module): + + def __init__(self): + super(Txt, self).__init__() + self.model = MODEL + + def forward(self, text, attention_mask): + with torch.no_grad(): + text = text.to(DEVICE) + attention_mask = attention_mask.to(DEVICE) + return self.model.get_text_features(text, attention_mask=attention_mask) + + +class TxtNorm(Txt): + + def forward(self, text, attention_mask): + return norm(super(TxtNorm, self).forward(text, attention_mask)) + + +IMG = Img() +IMG_NORM = ImgNorm() + +TXT = Txt() +TXT_NORM = TxtNorm() diff --git a/onnx/misc/config.py b/onnx/misc/config.py new file mode 100644 index 00000000..cd0e086b --- /dev/null +++ b/onnx/misc/config.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +from os.path import abspath, dirname, join +import os + +MODEL_NAME = os.getenv('MODEL') or 'AltCLIP-XLMR-L-m18' + +ROOT = dirname(dirname(abspath(__file__))) + +IMG_DIR = join(ROOT, 'test/img') +MODEL_DIR = join(ROOT, 'model') + +MODEL_FP = join(MODEL_DIR, MODEL_NAME) + +ONNX_DIR = join(ROOT, 'onnx', MODEL_NAME) + +ONNX_FP = join(ONNX_DIR, 'onnx') +PROCESS_DIR = join(ONNX_DIR, 'process') + +opset_version = 18 diff --git a/onnx/misc/device.py b/onnx/misc/device.py new file mode 100644 index 00000000..3f43e279 --- /dev/null +++ b/onnx/misc/device.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import torch +import os + +device = os.getenv('DEVICE') +if not device: + if torch.cuda.is_available(): + device = 'cuda' + elif torch.backends.mps.is_available(): + device = 'mps' + else: + device = 'cpu' + +DEVICE = torch.device(device) diff --git a/onnx/misc/norm.py b/onnx/misc/norm.py new file mode 100644 index 00000000..edbadf6a --- /dev/null +++ b/onnx/misc/norm.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python +import torch + + +# 对特征进行归一化 +def norm(vec): + with torch.no_grad(): + vec /= vec.norm(dim=-1, keepdim=True) + return vec diff --git a/onnx/misc/proc.py b/onnx/misc/proc.py new file mode 100755 index 00000000..04b36e9f --- /dev/null +++ b/onnx/misc/proc.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python + +from .config import PROCESS_DIR +from transformers import CLIPProcessor + + +class AltCLIPProcess(CLIPProcessor): + tokenizer_class = ("XLMRobertaTokenizer", "XLMRobertaTokenizerFast") + + def __init__(self, feature_extractor, tokenizer): + super().__init__(feature_extractor, tokenizer) + + +proc = AltCLIPProcess.from_pretrained(PROCESS_DIR) + +_tokenizer = proc.tokenizer +_transform = proc.feature_extractor + + +def transform(img): + img = _transform(img) + return img['pixel_values'] + + +def tokenizer(li): + tokenizer_out = _tokenizer(li, + padding=True, + truncation=True, + max_length=77, + return_tensors='pt') + text = tokenizer_out["input_ids"] + attention_mask = tokenizer_out["attention_mask"] + return text, attention_mask diff --git a/onnx/onnx/.keep b/onnx/onnx/.keep new file mode 100644 index 00000000..e69de29b diff --git a/onnx/os/root/.config/pip/pip.conf b/onnx/os/root/.config/pip/pip.conf new file mode 100644 index 00000000..5b7fab99 --- /dev/null +++ b/onnx/os/root/.config/pip/pip.conf @@ -0,0 +1,3 @@ +[global] +break-system-packages=true + diff --git a/onnx/test/clip/clip_img.py b/onnx/test/clip/clip_img.py new file mode 100755 index 00000000..1da276d6 --- /dev/null +++ b/onnx/test/clip/clip_img.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +from misc.proc import transform +from misc.clip_model import IMG +import torch + + +def img2vec(img): + img = transform(img) + img = torch.tensor(img) + return IMG.forward(img) + + +if __name__ == "__main__": + from misc.config import IMG_DIR + from misc.norm import norm + from os.path import join + from PIL import Image + + fp = join(IMG_DIR, 'cat.jpg') + img = Image.open(fp) + vec = img2vec(img) + print('vec', vec) + print('norm', norm(vec)) diff --git a/onnx/test/clip/clip_test.py b/onnx/test/clip/clip_test.py new file mode 100755 index 00000000..a0e04b71 --- /dev/null +++ b/onnx/test/clip/clip_test.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +import torch +from PIL import Image +from os.path import basename, join +from time import time +from clip_txt import txt2vec +from clip_img import img2vec + +COST = None + + +def inference(img, tmpl_kind_li): + global COST + image = Image.open(img) + begin = time() + image_features = img2vec(image) + if COST is not None: + COST += (time() - begin) + + for tmpl, kind_li in tmpl_kind_li: + li = [] + for i in kind_li: + li.append(tmpl % i) + + begin = time() + text_features = txt2vec(li) + if COST is not None: + COST += (time() - begin) + + with torch.no_grad(): + text_probs = (image_features @ text_features.T).softmax(dim=-1) + + for kind, p in zip(kind_li, text_probs.cpu().numpy()[0].tolist()): + p = round(p * 10000) + if p: + print(" %s %.2f%%" % (kind, p / 100)) + return + + +if __name__ == "__main__": + from misc.config import IMG_DIR + from glob import glob + li = glob(join(IMG_DIR, '*.jpg')) + # 预热,py.compile 要第一次运行才编译 + inference(li[0], + (('a photo of %s', ('cat', 'rat', 'dog', 'man', 'woman')), )) + COST = 0 + for i in li: + print("\n* " + basename(i)) + inference(i, (('a photo of %s', ('cat', 'rat', 'dog', 'man', 'woman')), + ('一张%s的图片', ('猫', '老鼠', '狗', '男人', '女人')))) + print('\ncost %2.fms' % (1000 * COST)) diff --git a/onnx/test/clip/clip_txt.py b/onnx/test/clip/clip_txt.py new file mode 100755 index 00000000..9bde55a9 --- /dev/null +++ b/onnx/test/clip/clip_txt.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +from misc.proc import tokenizer +from misc.clip_model import TXT + + +def txt2vec(li): + return TXT.forward(*tokenizer(li)) + + +if __name__ == "__main__": + from os.path import join + from glob import glob + from misc.config import ROOT + from test_txt import TEST_TXT + from misc.norm import norm + + li = glob(join(ROOT, 'jpg/*.jpg')) + for li in TEST_TXT: + r = txt2vec(li) + for txt, vec in zip(li, r): + print(txt) + print('vec', vec) + print('norm', norm(vec)) + print('\n') diff --git a/onnx/test/clip/test_txt.py b/onnx/test/clip/test_txt.py new file mode 120000 index 00000000..6e5c26bf --- /dev/null +++ b/onnx/test/clip/test_txt.py @@ -0,0 +1 @@ +../onnx/test_txt.py \ No newline at end of file diff --git a/onnx/test/img/build.jpg b/onnx/test/img/build.jpg new file mode 100644 index 00000000..a959e074 Binary files /dev/null and b/onnx/test/img/build.jpg differ diff --git a/onnx/test/img/cat.jpg b/onnx/test/img/cat.jpg new file mode 100644 index 00000000..887a369e Binary files /dev/null and b/onnx/test/img/cat.jpg differ diff --git a/onnx/test/img/dog.jpg b/onnx/test/img/dog.jpg new file mode 100644 index 00000000..dcea1f89 Binary files /dev/null and b/onnx/test/img/dog.jpg differ diff --git a/onnx/test/img/man.jpg b/onnx/test/img/man.jpg new file mode 100644 index 00000000..ea688c54 Binary files /dev/null and b/onnx/test/img/man.jpg differ diff --git a/onnx/test/img/rat.jpg b/onnx/test/img/rat.jpg new file mode 100644 index 00000000..460eb6a4 Binary files /dev/null and b/onnx/test/img/rat.jpg differ diff --git a/onnx/test/img/woman.jpg b/onnx/test/img/woman.jpg new file mode 100644 index 00000000..50fc137b Binary files /dev/null and b/onnx/test/img/woman.jpg differ diff --git a/onnx/test/onnx/onnx_img.py b/onnx/test/onnx/onnx_img.py new file mode 100755 index 00000000..67f5b109 --- /dev/null +++ b/onnx/test/onnx/onnx_img.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +from misc.proc import transform +from PIL import Image +from onnx_load import onnx_load + +IMG = onnx_load('Img') + + +def img2vec(img): + return IMG.run(None, {'input': transform(img)})[0] + + +if __name__ == '__main__': + from misc.config import IMG_DIR + from os.path import join + img = Image.open(join(IMG_DIR, 'cat.jpg')) + + img_data = transform(img) + vec = img2vec(img) + print('vec', vec) + IMG_NORM = onnx_load('ImgNorm') + print('norm', IMG_NORM.run(None, {'input': img_data})[0]) + + # from json import dumps + # print(dumps(img_data[0].tolist())) diff --git a/onnx/test/onnx/onnx_load.py b/onnx/test/onnx/onnx_load.py new file mode 100755 index 00000000..9849a15d --- /dev/null +++ b/onnx/test/onnx/onnx_load.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python + +import onnxruntime +from misc.config import ONNX_FP +from os.path import join +import os + +session = onnxruntime.SessionOptions() +option = onnxruntime.RunOptions() +option.log_severity_level = 2 + + +def onnx_load(kind): + fp = join(ONNX_FP, f'{kind}.onnx') + provider = os.getenv('ONNX_PROVIDER') + providers = [provider] if provider else None + sess = onnxruntime.InferenceSession(fp, + sess_options=session, + providers=providers) + return sess + + +if __name__ == '__main__': + from onnxruntime import get_all_providers + print('all providers :\n%s\n' % get_all_providers()) + sess = onnx_load('Txt') + providers = sess.get_providers() + print('now can use providers :\n%s\n' % providers) diff --git a/onnx/test/onnx/onnx_test.py b/onnx/test/onnx/onnx_test.py new file mode 100755 index 00000000..e5e3b540 --- /dev/null +++ b/onnx/test/onnx/onnx_test.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +from torch import tensor +import torch +from PIL import Image +from os.path import basename, join +from time import time +from onnx_txt import txt2vec +from onnx_img import img2vec + +COST = None + + +def inference(img, tmpl_kind_li): + global COST + image = Image.open(img) + begin = time() + image_features = img2vec(image) + if COST is not None: + COST += (time() - begin) + + for tmpl, kind_li in tmpl_kind_li: + li = [] + for i in kind_li: + li.append(tmpl % i) + + begin = time() + text_features = txt2vec(li) + if COST is not None: + COST += (time() - begin) + + with torch.no_grad(): + image_features = tensor(image_features) + text_features = tensor(text_features) + text_probs = (image_features @ text_features.T).softmax(dim=-1) + + for kind, p in zip(kind_li, text_probs.cpu().numpy()[0].tolist()): + p = round(p * 10000) + if p: + print(" %s %.2f%%" % (kind, p / 100)) + return + + +if __name__ == "__main__": + from misc.config import IMG_DIR + from glob import glob + li = glob(join(IMG_DIR, '*.jpg')) + # 预热,py.compile 要第一次运行才编译 + inference(li[0], + (('a photo of %s', ('cat', 'rat', 'dog', 'man', 'woman')), )) + COST = 0 + for i in li: + print("\n* " + basename(i)) + inference(i, (('a photo of %s', ('cat', 'rat', 'dog', 'man', 'woman')), + ('一张%s的图片', ('猫', '老鼠', '狗', '男人', '女人')))) + print('\ncost %2.fms' % (1000 * COST)) diff --git a/onnx/test/onnx/onnx_txt.py b/onnx/test/onnx/onnx_txt.py new file mode 100755 index 00000000..41aac728 --- /dev/null +++ b/onnx/test/onnx/onnx_txt.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +from misc.proc import tokenizer +from onnx_load import onnx_load + +TXT = onnx_load('Txt') + + +def txt2vec(li): + text, attention_mask = tokenizer(li) + text = text.numpy() + attention_mask = attention_mask.numpy() + output = TXT.run(None, {'input': text, 'attention_mask': attention_mask}) + return output[0] + + +if __name__ == '__main__': + + from test_txt import TEST_TXT + + TXT_NORM = onnx_load('TxtNorm') + + for li in TEST_TXT: + r = txt2vec(li) + text, attention_mask = tokenizer(li) + text = text.numpy() + attention_mask = attention_mask.numpy() + output = TXT_NORM.run(None, { + 'input': text, + 'attention_mask': attention_mask + })[0] + for txt, vec, norm in zip(li, r, output): + print(txt) + print('vec', vec) + print('norm', norm) + print('\n') diff --git a/onnx/test/onnx/requirements.txt b/onnx/test/onnx/requirements.txt new file mode 100644 index 00000000..976a2b1f --- /dev/null +++ b/onnx/test/onnx/requirements.txt @@ -0,0 +1 @@ +transformers diff --git a/onnx/test/onnx/setup.sh b/onnx/test/onnx/setup.sh new file mode 100755 index 00000000..d508ff3c --- /dev/null +++ b/onnx/test/onnx/setup.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +DIR=$(realpath $0) && DIR=${DIR%/*} +cd $DIR +set -ex + +pip install -r ./requirements.txt +if [ -x "$(command -v nvidia-smi)" ]; then + pip install onnxruntime-gpu +else + system=$(uname) + arch=$(uname -m) + if [[ $system == *"Darwin"* ]] && [[ $arch == "arm64" ]]; then + pip install onnxruntime-silicon + else + grep 'vendor_id' /proc/cpuinfo | awk '{print $3}' | grep 'GenuineIntel' >/dev/null + if [ $? -eq 0 ]; then + echo 'Intel CPU' + pip install onnxruntime-openvino + else + echo 'Non-Intel CPU' + pip install onnxruntime + fi + fi +fi diff --git a/onnx/test/onnx/test_txt.py b/onnx/test/onnx/test_txt.py new file mode 100644 index 00000000..0fa6707b --- /dev/null +++ b/onnx/test/onnx/test_txt.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python + +TEST_TXT = ( + ('a photo of dog', 'a photo for chinese woman'), + ('a photo of dog', 'a photo for cat'), +) diff --git a/onnx/version.txt b/onnx/version.txt new file mode 100644 index 00000000..3adae0ca --- /dev/null +++ b/onnx/version.txt @@ -0,0 +1 @@ +2023-07-31 diff --git a/setup.py b/setup.py index ab4a8553..1ffb2d85 100755 --- a/setup.py +++ b/setup.py @@ -6,7 +6,8 @@ setup( name="flagai", version="v1.7.3", - description="FlagAI aims to help researchers and developers to freely train and test large-scale models for NLP/CV/VL tasks.", + description= + "FlagAI aims to help researchers and developers to freely train and test large-scale models for NLP/CV/VL tasks.", long_description=open("README.md", encoding="utf-8").read(), long_description_content_type="text/markdown", author="FlagAI-Open", @@ -40,5 +41,4 @@ 'accelerate', 'PyYAML==5.4.1', 'safetensors', - ] -) + ])