DollyV2にインストラクションを提示して使ってみる（２）

# はじめに
[前回](https://qiita.com/tomofu74/items/a653faed4096187cbe4f)、なんかうまく行かなかったチャットを通じてのDollyさんとの組み手（格闘か？）、間違いかもしれない点を探りながら対応を修正してみる。そもそも、instruct_pipeline.py で定義されている、InstructionTextGenerationPipeline によって生成されるパイプラインを、当初のchatボットのパイプラインにそのまま使ってしまって、チャットの文言渡しただけで引数の受け渡しがうまくいっているのか？という疑問の解決からスタートし、速度改善の可能性なども検討してみる。


# Dollyさんとの付き合い方を調べる ~　Datablicksさんの instruct_pipeline.py で　〜

https://huggingface.co/databricks/dolly-v2-7b


そりゃそうだ。お互いに全然見も知らぬプログラム同士を組み合わせていきなりどんで動くわけねぇ・・・。ジャイナント馬場さん連れてきて、ハイそれでは所ジョーイチさんと、チャンバラしてくださーいってどんな台本だよ、ってな現場ぐらい動くわけねぇ・・・。えーっと、まず所さん（＝ チャットプログラム）を置いといて、連れてきた馬場さん（＝ instruct_pipeline.py)のできることを確認しよう。

早速だが、 馬場さんにはテキストの渡し方のフォーマットがあるようだ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699890/3b4a7fe8-1d14-e512-5dc2-503633768357.png)

で、このフォーマットを参照する箇所は、InstructionTextGenerationPipelineクラスの preprocess 関数。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699890/8aad6002-6753-bac8-cb27-6c07b2ecf5ae.png)

preprocess の引数でinstruction_textを引数にして、馬場さんFORMATに整形して改めてInputno引数（配列）の要素の一つにしてる。ってことは、キーワードを所さんで明示しないでよいってこと。所さんはインストラクション（指示）を文章で書けばよい、と。

それでいってみたところ
![Screenshot from 2023-04-16 21-49-23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699890/63c62b43-aa0a-2f57-b4ec-93628cc887a2.png)

時間はかかったけど、こちらの意図した（インストラクションした）とおりにタスクをこなした感がある。


# Pipeline

馬場さんは、そもそもどういう素性の人かというと、某団体（＝HuggingFace の Transformer）の選手（＝Pipeline）である。Transformerの Pipeline を継承した クラスが定義してあるってことよ。Pythonってクラス名の（）に親クラス名を書いて継承するのね。そういう書き方から知らずにいじってたよ、わたし。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699890/da1ad25e-0bf7-7e20-af2f-fe2655db4344.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699890/2b29ea29-93d1-ec9d-8c88-a8e2e95c6399.png)

さて、それでは、 Pipeline の高速化にはどんな方法があるのか。

まずは、推論速度を高速化する手法の調査をしてみた。

https://tech.jxpress.net/entry/2021/08/26/170000

うーん、かんたんで効果的っぽいのは、量子化かなぁ。かんたんと判断した理由は、modelの宣言のところでデータタイプの宣言を変えるだけでよさそうだったから。早速試してみた。
```python
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.qint8, device_map="auto")
```
さっそく、この設定でDollyさんを再起動。
・・・あれ？ エラー。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699890/55a00ad4-6d68-39eb-af95-f4498b5dd183.png)
この方法は使えないのか・・・じゃぁ、とりあえず、bfloat16で。
```python
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.bfloat16, device_map="auto")
```

さて、これで再起動。
さっきと同じタスクを所さんに入力。返事が返ってくるのがちょっと早くなった。少し時間短縮したきがする・・・。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699890/3c760d3e-1724-cb13-d724-e21b8426b93c.png)

おや？dtype変更まえと結果が異なるようだが・・・
課題の元のの文章には、実は続きがあって文章が途切れている。その途切れている部分について要約に盛り込んでいたのが、データタイプを変更するまえの応答。「何を言ったか」がわからないのに”なにか言ったぞ”として要約にあげているので、ちょっとセンスがない。データタイプ変更前は、デフォルトなのでなんだかわからないが torch_dtype=torch.bfloat32 だったのか。それに比べると、 torch_dtype=torch.bfloat16 にしたあとのほうが、今回のタスクとは相性がよかったのか、文章の要約としてはうまく抽出している気もする。

dtypeの指定前後とも「３点」に絞って文章を作るタスクをする、という意図（インストラクション）は伝わっているようだ。つまり、dtypeをbfloat16にしても、悪くなさげ、と解釈できる。

# まとめ
Dollyさんとのインストラクションを使った付き合い方がわかった。
処理の高速化のためにTransformerでは量子化という手法があり、HuggingFaceのTransformerでは、modelの設定引数のtorch_dtypeをtorch.bfloat16にすることで、処理精度をあまり変えずに処理時間を短縮できそうであることがわかった。

今後は、要約以外のいろいろなタスクをさせてみたい、と思う。


# おまけ。
NvidiaのGPUを使っているときにプロセスがメモリを開放してくれないときがあって・・・対処法も調べてみた。なんのことはない、nvidia絡みのプロセスを見つけて kill 斬る

https://qiita.com/miyamotok0105/items/033b850a205f958808e9