watsonx Code Assistant for Red Hat Ansible Lightspeed  のチューニング・データ作成

#### はじめに

watsonx Code Assistant for Red Hat Ansible Lightspeed (IBM Cloudのサービス) は 標準プランでは モデルのチューニングを実施することが可能です。

・[IBM watsonx Code Assistant for Red Hat Ansible Lightspeed 料金プラン](https://cloud.ibm.com/docs/watsonx-code-assistant?topic=watsonx-code-assistant-ansible-pricing)

> 標準プラン
標準プランは、タスク・プロンプト機能とモデル・チューニング機能の両方を含む、前払いの月次プランです。 このプランでは、自然言語要求からタスク・プロンプトを作成して、 Ansible コードを生成できます。 また、企業標準に合わせてカスタマイズされたコード提案を生成するように、独自のデータに対して IBM 基本コード・モデルを調整することもできます。


今回は チューニングのための"JSONL 形式 のチューニング・データ" を作成します。

・[IBM Cloud docs: watsonx Code Assistant for Red Hat Ansible Lightspeed の IBM 基本コード・モデルのチューニング](https://cloud.ibm.com/docs/watsonx-code-assistant?topic=watsonx-code-assistant-tutorial-tune-ansible&locale=ja)

> チューニング・データを JSONL 形式でアップロードします。


作成方法は、RedHat のマニュアルを確認します。


・[RedHat コンテンツパーサーツールを使用したトレーニングデータセットの作成](https://access.redhat.com/documentation/ja-jp/red_hat_ansible_lightspeed_with_ibm_watsonx_code_assistant/2.x_latest/html/red_hat_ansible_lightspeed_with_ibm_watsonx_code_assistant_user_guide/ansible-content-parser_configuring-custom-models)


----

#### python 仮想環境作成

・ python 仮想環境 "sample1" を設定

```
$ python -m venv ./sample1
$ echo $?
0
$ ls -l ./sample1
total 8
drwxr-xr-x  12 user1  staff  384  4 26 15:17 bin
drwxr-xr-x   3 user1  staff   96  4 26 15:17 include
drwxr-xr-x   3 user1  staff   96  4 26 15:17 lib
-rw-r--r--   1 user1  staff  305  4 26 15:17 pyvenv.cfg
$
```

・仮想環境 sample1 の activate


```
$ source ./sample1/bin/activate
(sample1) $
(sample1) $ python --version
Python 3.12.3
```

python のバージョンは 3.12.3 です。

---

#### ansible-content-parser コマンドを導入

* ansible-content-parser とは

>ansible-content-parser は 特定のソース (ローカル ディレクトリ、アーカイブ ファイル、または git URL) 内の Ansible ファイルを分析し、 自動修正の機能 ansible-lintを使用して Ansible ファイルを更新し 、カスタム AI モデルを開発するためのトレーニング データセットである"ftdata.jsonl" ファイルを生成します。

https://github.com/ansible/ansible-content-parser


* ansible-lint とは

https://ansible.readthedocs.io/projects/lint/

> Ansible Lint は、あらゆる Ansible ユーザーを対象としたプレイブック、ロール、コレクションの内容を分析し、問題点を指摘するためのコマンドライン・ツールです。


<br>

・ pip リポジトリーから最新バージョンのコンテンツパーサーツールをインストール

```
(sample1) $ pip install --upgrade pip
Requirement already satisfied: pip in ./sample1/lib/python3.12/site-packages (24.0)
(sample1) $

pip のアップグレードは追加なし。

(sample1) $ pip install --upgrade ansible-content-parser

~ 長いログを省略。以下のパッケージが導入されました。~ 


Successfully installed GitPython-3.1.43 Levenshtein-0.25.1 MarkupSafe-2.1.5 
ansible-compat-4.1.11 ansible-content-parser-1.0.3 ansible-core-2.16.6 
ansible-lint-24.2.1 ansible-risk-insight-0.2.5 attrs-23.2.0 black-23.7.0 
bracex-2.4 certifi-2024.2.2 cffi-1.16.0 charset-normalizer-3.3.2 click-8.1.7 
contourpy-1.2.1 cryptography-42.0.5 cycler-0.12.1 filelock-3.13.4 
fonttools-4.51.0 gitdb-4.0.11 giturlparse-0.12.0 idna-3.7 jinja2-3.1.3 
joblib-1.4.0 jsonpath-ng-1.6.1 jsonpickle-3.0.4 jsonschema-4.21.1 
jsonschema-specifications-2023.12.1 kiwisolver-1.4.5 lxml-5.2.1 
markdown-it-py-3.0.0 matplotlib-3.8.4 mdurl-0.1.2 mypy-extensions-1.0.0 
numpy-1.26.4 packaging-24.0 pathspec-0.12.1 pillow-10.3.0 platformdirs-4.2.1 
ply-3.11 pycparser-2.22 pygments-2.17.2 pyparsing-3.1.2 python-dateutil-2.9.0.post0 
python-docx-0.8.11 pyyaml-6.0.1 rapidfuzz-3.8.1 referencing-0.35.0 
requests-2.31.0 resolvelib-1.0.1 rich-13.7.1 rpds-py-0.18.0 
ruamel.yaml-0.18.6 ruamel.yaml.clib-0.2.8 sage-scan-0.0.4 sarif-tools-2.0.0 
six-1.16.0 smmap-5.0.1 subprocess-tee-0.4.1 tabulate-0.9.0 
treelib-1.7.0 urllib3-2.2.1 wcmatch-8.5.1 yamllint-1.35.1
(sample1) $
```

・ansible-content-parser を試行。エラーが出ます。

```
(sample1) $ ansible-content-parser --version
Traceback (most recent call last):
~省略~
ModuleNotFoundError: No module named 'pkg_resources'
(sample1) $
```

上記エラーでは setuptools を導入、upgrade して解決している例があるので同じようにsetuptoolsのアップグレードを試してみます。

```
(sample1) $ pip install --upgrade setuptools
~省略~
Successfully installed setuptools-69.5.1
```

・再度 ansible-content-parser コマンドを打つと、'pygit2'が見つからないエラーが出力

```
(sample1) $ ansible-content-parser --version
Traceback (most recent call last):
ModuleNotFoundError: No module named 'pygit2'
```

'pygit2' を導入、アップグレードします。

```
(sample1) $ pip install --upgrade pygit2
~省略~
Successfully installed pygit2-1.14.1
(sample1) $
```

・再々度 ansible-content-parser コマンドを実行

```
(sample1) $ ansible-content-parser --version
ansible-content-parser 1.0.3 using ansible-lint:24.2.1 ansible-core:2.16.6 sage-scan:0.0.4
(sample1) $
```

成功!
仮想環境 sample1 で ansible-content-parser コマンドが打てるようになりました。

<br>

・ansible-lint コマンドの確認

```
(sample1) $ ansible-lint --version
ansible-lint 24.2.1 using ansible-core:2.16.6 ansible-compat:4.1.11 ruamel-yaml:0.18.6 ruamel-yaml-clib:0.2.8
A new release of ansible-lint is available: 24.2.1 → 24.2.2 Upgrade by running: pip install --upgrade ansible-lint
(sample1) $
```

ansible-lint のバージョンは 24.2.1 を使用しており、ansible-content-parser コマンドが使用する ansible-lint バージョンと同じです。
ansible-lint コマンドのアップデートは実施しません。


---

#### チューニング・データセットの生成


・ansible-content-parser コマンドの確認

```
(sample1) $ ansible-content-parser --help
usage: ansible-content-parser [-h] [--config-file CONFIG_FILE]
                              [--profile {min,basic,moderate,safety,shared,production}]
                              [--fix WRITE_LIST] [-S] [--no-exclude] [-v]
                              [--source-license SOURCE_LICENSE]
                              [--source-description SOURCE_DESCRIPTION] [--repo-name REPO_NAME]
                              [--repo-url REPO_URL] [--version]
                              source output

Parse Ansible files in the given repository by running ansible-lint and generate a training
dataset for Ansible Lightspeed.

positional arguments:
  source                source, which can be an zip/tar archive, a git URL or a local directory
  output                output directory

options:
  -h, --help            show this help message and exit
  --config-file CONFIG_FILE
                        Specify the configuration file to use for ansible-lint. By default it will
                        look for '.ansible-lint', '.config/ansible-lint.yml', or '.config/ansible-
                        lint.yaml' in the source repository.
  --profile {min,basic,moderate,safety,shared,production}
                        Specify which rules profile to be used for ansible-lint
  --fix WRITE_LIST      Specify how ansible-lint performs auto-fixes, including YAML reformatting.
                        You can limit the effective rule transforms (the 'write_list') by passing
                        a keywords 'all' (=default) or 'none' or a comma separated list of rule
                        ids or rule tags.
  -S, --skip-ansible-lint
                        Skip the execution of ansible-lint.
  --no-exclude          Do not let ansible-content-parser to generate training dataset by
                        excluding files that caused lint errors. With this option specified, a
                        single lint error terminates the execution without generating the training
                        dataset.
  -v, --verbose         Explain what is being done
  --source-license SOURCE_LICENSE
                        Specify the license that will be included in the training dataset.
  --source-description SOURCE_DESCRIPTION
                        Specify the description of the source that will be included in the
                        training dataset.
  --repo-name REPO_NAME
                        Specify the repository name that will be included in the training dataset.
                        If it is not specified, it is generated from the source name.
  --repo-url REPO_URL   Specify the repository url that will be included in the training dataset.
                        If it is not specified, it is generated from the source name.
  --version             show program's version number and exit
(sample1) $
```

ansible-lint で前処理をする方法 (--profile オプションを指定)で、ansible-content-parser コマンドを実行します。

<br>


ソース、aix_mount というディレクトリを指定で実行します。
今回は手順確認のため、１つのディレクトリに ibm.power_aix.mount モジュールのサンプルが記載された 1つの playbook ファイルのみの内容です。

ソースは他にもGit リポジトリーのURL や zip ファイル、tarファイルが指定可能です。

| 項目 | 指定値| 意味 |
|:-----------:|:------------:|:------------:|
| source     | ./aix_mount   | local directory を指定     |
| output     | ./aix_mount_output  | データセットの出力先       |
| --profile  | safety      | Ansible-lint ルールの厳格さ   |
| -v        |  (指定なし)      | 詳細出力           |


アウトプット先のディレクトリを作成

```
(sample1) $ mkdir aix_mount_output
(sample1) $
```

```
(sample1) $ ls -l aix_mount
total 8
-rw-r--r--@ 1 user  staff  1332  4 26 14:36 aix_mount.yml
```

```
(sample1) $ ansible-content-parser --profile safety ./aix_mount ./aix_mount_output -v
INFO     Identified / as project root due file system root.
INFO     Set ANSIBLE_LIBRARY=/Users/user1/.cache/ansible-compat/e2885f/modules:/Users/user1/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO     Set ANSIBLE_COLLECTIONS_PATH=/Users/user1/.cache/ansible-compat/e2885f/collections:/Users/user1/.ansible/collections:/usr/share/ansible/collections
INFO     Set ANSIBLE_ROLES_PATH=/Users/user1/.cache/ansible-compat/e2885f/roles:/Users/user1/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
INFO     Set ANSIBLE_LIBRARY=/Users/user1/.cache/ansible-compat/e2885f/modules:/Users/user1/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO     Set ANSIBLE_COLLECTIONS_PATH=/Users/user1/.cache/ansible-compat/e2885f/collections:/Users/user1/.ansible/collections:/usr/share/ansible/collections
INFO     Set ANSIBLE_ROLES_PATH=/Users/user1/.cache/ansible-compat/e2885f/roles:/Users/user1/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
INFO     Executing syntax check on playbook aix_mount.yml (0.24s)

Passed: 0 failure(s), 0 warning(s) on 1 files. Profile 'safety' was required, but 'production' profile passed.
Writing summary of sarif.json to /Users/user1/Desktop/Code/sample1/aix_mount_output/metadata/sarif_summary.txt
DEBUG    ARI KB data dir is not configured.
INFO     Running data pipeline
INFO     Start scanning for 1 projects (total 1 files)
DEBUG    [1/1] start project repository
INFO     Done
INFO     Training data set was created at /Users/user1/Desktop/Code/sample1/aix_mount_output/ftdata.jsonl.
INFO     Execution report was generated at /Users/user1/Desktop/Code/sample1/aix_mount_output/report.txt.
(sample1) $
```


```
(sample1) $ ls -lR ./aix_mount_output
total 32
-rw-r--r--  1 user1  staff  8632  4 26 16:38 ftdata.jsonl #<=このファイルを使用
drwxr-xr-x  7 user1  staff   224  4 26 16:38 metadata
-rw-r--r--  1 user1  staff  1185  4 26 16:38 report.txt
drwxr-xr-x  3 user1  staff    96  4 26 16:38 repository

./aix_mount_output/metadata:
total 64
-rw-r--r--  1 user1  staff    448  4 26 16:38 file_inventory.json
-rw-r--r--  1 user1  staff    273  4 26 16:38 lint-result.json
-rw-r--r--  1 user1  staff   2446  4 26 16:38 sage-metadata.json
-rw-r--r--  1 user1  staff  16161  4 26 16:38 sage-objects.json
-rw-r--r--  1 user1  staff    428  4 26 16:38 sarif.json

./aix_mount_output/repository:
total 8
-rw-r--r--  1 user1  staff  1302  4 26 16:38 aix_mount.yml
(sample1) $
```

実行内容は report.txt にまとめられています。

```
(sample1) $(sample1) $ cat ./aix_mount_output/report.txt
********************************************************************************
****                Ansible Content Parser Execution Report                 ****
********************************************************************************

Date/Time             : 2024-04-26T07:38:56.804308+00:00
Content Parser Version: 1.0.3
Source Repository     : ./aix_mount
Output Directory      : /Users/user1/Desktop/Code/sample1/aix_mount_output

[ File counts per type ]

-------------------
File Type     Count
-------------------
playbook          1
-------------------
TOTAL             1
-------------------

[ List of Ansible files identified ]
--------------------------------------------
File Path      File Type  Excluded/Autofixed
--------------------------------------------
aix_mount.yml  playbook
--------------------------------------------

[ Issues found by ansible-lint ]

error: 0
warning: 0
note: 0

[ List of Ansible modules found in tasks ]
-----------------------------
Module Name             Count
-----------------------------
ibm.power_aix.mount         8
-----------------------------
TOTAL                       8
-----------------------------
(sample1) $
```


トレーニング・データ本体の ftdata.jsonl を見てみます。


```
(sample1) $ cat aix_mount_output/ftdata.jsonl
{"data_source_description": "", "input": "---\n- name: MOUNT on AIX\n  hosts: aixserver1\n  collections:\n    - ibm.power_aix\n  vars:\n    host_name: all\n    mount_dir_value: /mnt/testfs\n    mount_over_dir_value: /mnt/clientnfs\n    node_v: ansible-test1\n  tasks:\n    - name: List mounted filesystems", "license": "", "module": "ibm.power_aix.mount", "output": "      ibm.power_aix.mount:\n        state: show\n", "path": "aix_mount.yml", "repo_name": "aix_mount", "repo_url": "file:///XX/XXX/XXX/sample1/aix_mount"}
{"data_source_description": "", "input": "---\n- name: MOUNT on AIX\n  hosts: aixserver1\n  collections:\n    - ibm.power_aix\n  vars:\n    host_name: all\n    mount_dir_value: /mnt/testfs\n    mount_over_dir_value: /mnt/clientnfs\n    node_v: ansible-test1\n  tasks:\n    - name: List mounted filesystems\n      ibm.power_aix.mount:\n        state: show\n\n    - name: Mount filesystems", "license": "", "module": "ibm.power_aix.mount", "output": "      ibm.power_aix.mount:\n        state: mount\n        mount_dir: \"{{ mount_dir_value }}\"\n", "path": "aix_mount.yml", "repo_name": "aix_mount", "repo_url": "file:///XX/XXX/XXX/sample1/aix_mount"}

~ 省略。上記のような行が続きます。~
```


IBM Cloud watsonx Code Assistant for Red Hat Ansible Lightspeed のモデルをチューニングするための ftdata.jsonl ファイルが作成できました。


<br>

カスタマイズ・モデルの作成は以下で確認しています。

https://qiita.com/c_u/items/d2942a4a9308f8a7dcac




以上です。