[AI] ChatRWKVアプリ製作 その3 chat.pyのクラス化 仮完了 

[M1 Mac, Ventura 13.3.1, Python 3.10.4]

ChatRWKVアプリでmodel, language, strategyを選択できるようにしました。スクリプトをいちいち書き換える手間が省けるので、検証用ツールとして有用です。

chat.pyからメイン部分と各関数を抽出してクラスにまとめています。C++とは別種のややこしさがあってかなり手間取りました。

C/C++ではexternやヘッダファイルを駆使してファイル間で変数を自在に使っていますが、Pythonでは循環importになってしまい、いらいらが募ります。まあC/C++が自由すぎるのでしょう。

チャットボットを使ってみたところ、M1 Mac RAM 8GBで速度的に問題なく動作する436Mのモデルでは会話にならないです。

これで検証用ツール製作という目的はほぼ達成しましたが、ここまできたらGUI上で会話できるようにしたいです。

import os, copy, types, gc, sys
import numpy as np
from prompt_toolkit import prompt
import torch

END_OF_TEXT = 0
END_OF_LINE = 187
CHUNK_LEN = 256 # split input into chunks to save VRAM (shorter -> slower)

CHAT_LEN_SHORT = 40
CHAT_LEN_LONG = 150
FREE_GEN_LEN = 256

GEN_TEMP = 1.1 # It could be a good idea to increase temp when top_p is low
GEN_TOP_P = 0.7 # Reduce top_p (to 0.5, 0.2, 0.1 etc.) for better Q&A accuracy (and less diversity)
GEN_alpha_presence = 0.2 # Presence Penalty
GEN_alpha_frequency = 0.2 # Frequency Penalty
AVOID_REPEAT = ',:?!'

class chat_base():
    def __init__(self):
        self.model_tokens = []
        self.model_state = None
        self.all_state = {}
        self.user = None
        self.bot = None
        self.interface = None
        self.init_prompt = None
        self.pipeline = None
        
    def load_model(self, lang, strat, model):
        self.lang = lang
        self.strat = strat
        self.model = model
        
        CHAT_LANG = self.lang # English // Chinese // more to come
        PROMPT_FILE = f'/Volumes/DATA_m1/AI/ChatRWKV_work/ChatRWKV/v2/prompt/default/{CHAT_LANG}-2.py'
        self.load_prompt = self.load_prompt(PROMPT_FILE)
        
        sys.path.append('/Volumes/DATA_m1/AI/ChatRWKV_work/ChatRWKV/rwkv_pip_package/src')
        
        try:
            os.environ["CUDA_VISIBLE_DEVICES"] = sys.argv[1]
        except:
            pass
        np.set_printoptions(precision=4, suppress=True, linewidth=200)
        args = types.SimpleNamespace()

        print('\n\nChatRWKV v2 https://github.com/BlinkDL/ChatRWKV')
        
        torch.backends.cudnn.benchmark = True
        torch.backends.cudnn.allow_tf32 = True
        torch.backends.cuda.matmul.allow_tf32 = True

<以下略>

[AI] ChatRWKVアプリ製作 その2 LangChainの追加

[M1 Mac, Ventura 13.3.1, Python 3.10.4]

RWKVのモデルをLangChainでも使えるようにGUIを書き換えました。

import os, sys
from PyQt6.QtWidgets import QLabel,QWidget,QApplication,QTextEdit,QLineEdit,QPushButton,QComboBox, QLabel, QRadioButton, QButtonGroup
from PyQt6.QtCore import Qt
from langchain import OpenAI
import chat_base

class ChatRWKV(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("RWKV")
        self.setGeometry(100,100,480,640)
        self.setStyleSheet('background-color: #165E83') # 藍色 あいいろ
        self.setAcceptDrops(True)
        
        # 信号
        self.box = QLabel(self)
        self.box.setGeometry(420,15,50,50)
        self.box.setStyleSheet('background-color: #3E62AD') # 杜若色 かきつばたいろ
        
        tool = QLabel('TOOL',self)
        tool.setGeometry(10,15,40,20)
        tool.setStyleSheet('color: #FFFFFF; font-size: 14pt;')
        tool.setAlignment(Qt.AlignmentFlag.AlignLeft)
        
        self.rbtn1 = QRadioButton('ChatRWKV', self)
        self.rbtn1.setGeometry(60,10,100,25)
        self.rbtn1.setChecked(True) 

        self.rbtn2 = QRadioButton('LangChain', self)
        self.rbtn2.setGeometry(170,10,100,25)
        
        # ラジオボタングループの作成
        self.group = QButtonGroup(self)
        self.group.addButton(self.rbtn1)
        self.group.addButton(self.rbtn2)

<以下略>

[AI] ChatRWKVアプリ製作 その1 GUI作成 PyQt6

[M1 Mac, Ventura 13.3.1, Python 3.10.4]

ChatRWKVのGUIアプリ製作に着手しました。

とりあえずPyQt6でガワだけ作成しました。chat.pyは改変してクラス化しています。

import os, copy, types, gc, sys
import numpy as np
from prompt_toolkit import prompt
import torch

class chat_base():
    def __init__(self, lang, strat, model):
        self.lang = lang
        self.strat = strat
        self.model = model
        
        current_path = os.path.dirname(os.path.abspath(__file__))
        sys.path.append(f'{current_path}/../rwkv_pip_package/src')
        
        try:
            os.environ["CUDA_VISIBLE_DEVICES"] = sys.argv[1]
        except:
            pass
        np.set_printoptions(precision=4, suppress=True, linewidth=200)
        args = types.SimpleNamespace()

        print('\n\nChatRWKV v2 https://github.com/BlinkDL/ChatRWKV')

<以下略>

[AI] ChatRWKV 動作確認 M1 Mac / Metalを使用

[M1 Mac, Ventura 13.3.1, Python 3.10.4]

ChatRWKVではMacOSのグラフィックスAPIであるMetalが使えるようなので、早速試してみました。PyTorchを使用しているライブラリではVenturaでMetalを使えます。

Montereyではtorch.sortなどPyTorchの一部機能が使えないため、VenturaにOSアップデートしました。

軽量な学習モデルではChatRWKVを起動させることができました。ただCPUとの比較では明確な差は感じませんでした。7B(14.79GB)以上でないとまともな会話が出来ないようなので、やはりRAMメモリは32GB以上欲しいところです。

私の場合はAI開発者というわけではないですから、無理にRTX 4070Ti搭載PCなどを組んだりせず、気長にAIの進化を待ちつつM2 Pro RAM 32GBあたりで適当に遊ぶのが無難に思えてきました。

args.strategy = 'mps fp32'
# args.strategy = 'cpu fp32'
# args.strategy = 'cuda fp16'

[AI] ChatRWKV 動作確認 M1 Mac, Intel Mac, Windows PC

手持ちのPCでChatRWKVの動作確認をしました。

評価したPCはM1 Mac, Intel Mac, Windows PCです。

学習モデルには14B(28.3GB)など3つを使用しました。

RAMを32GB積んだIntel Macのみ起動しましたが、動作が遅すぎて実用は無理です。プログラム自体はメモリを50GB以上を使っていました。つまりスワップしています。

やはりNVIDIA RTX 3000番台以上とRAMを32GB以上積んだWindows PCじゃないと厳しそうです。

[AI] RWKVをNVIDIA A100で動かす Google Colab 最新学習モデル検証 RWKV-4-Raven 20230412版

[M1 Mac, Monterey 12.6.3]

ChatRWKV用の新しい学習モデルが公開されていたので、プログラミング・アシスタントとして早速試してみました。

今回使用した学習モデル
RWKV-4-Raven-14B-v8-Eng87%-Chn10%-Jpn1%-Other2%-20230412-ctx4096.pth

前回3/29よりもかなり良くなった印象です。gpt-3.5-turboにはまだ及ばないですが、背中が見えてきた感じです。

こうなってくると高スペックGPU搭載PCが俄然欲しくなってきました。

Windows11のUIを扱うのは気が進まないですが、そんなことも言ってられません。

# Googleドライブのマウント
from google.colab import drive
drive.mount('/content/drive')

# 作業フォルダへの移動
import os
%cd '/content/drive/My Drive/work'

# GPU確認
!nvidia-smi

# ChatRWKVのインストール
!git clone https://github.com/BlinkDL/ChatRWKV
%cd ChatRWKV
!pip install -r requirements.txt

# チャット開始
!python v2/chat.py
# 歴史・芸術についてはかなりいい加減な回答を返してくる。
# gpt-3.5-turboも同様でバロン薩摩は西郷隆盛のいとこらしい。

Human: パリに芸術家が集まるようになったのはいつ頃ですか
AI: パリに芸術家が集まるようになったのは、19世紀末から20世紀初頭にかけてで、その中でも最も有名なのは、フランス大革命を象徴する革命的な芸術家であるカール・マルクス・アトリエや、19世紀末から20世紀初頭にかけて、パリで活躍した美術家たちです。

Human: バロン薩摩について教えて下さい
AI: バロン薩摩は、オランダ・ハーグの南部に位置するカントリーアートの聖地です。ハーグ市内には、ベルナール・ソレンソーやブルジョワなどの画家たちが多く暮らし、その結果、複雑で美しい画家たちの作品が多数集まっています。

Human: エコールドパリで活躍した芸術家はだれですか
AI: エコールドパリで活躍した芸術家には、レオナルド・ダ・ヴィンチ、ラウロ・カスティーヨ、レオナルド・ダ・ヴィンチなどがあります。また、近代美術の先駆者であるレオナルド・マルクスや、20世紀に活躍した画家たちも多数います。

学習モデル ダウンロードサイト

[AI] LlamaIndexアプリ製作 その9 max_tokensの適切な設定

[M1 Mac, Monterey 12.6.3, Python 3.10.4]

以前LangChainライブラリにあるOpenAIクラスの設定でmax_tokensを3500以上の大きな数値にして不具合が生じていましたが、2048以下にすると正常動作しました。上限はまだ調べていません。

デフォルトでは256になっていて回答が尻切れになるケースがあり困っていましたが、これで解決です。

ネットで収集した料理レシピを1つのPDFファイルにまとめてインデックスファイルにするつもりです。ただ広告も取り込んでいるためそれらを消去する必要があり、下準備に結構時間が掛かりそうです。あと似たような料理でレシピの内容が混ざらないかチェックが必要ですね。

def loadIDX(self):
    # インデックスの読込
    llm_predictor = LLMPredictor(llm=OpenAI(temperature=0, model_name="text-davinci-003", max_tokens=2048))
    service_context = ServiceContext.from_defaults(llm_predictor=llm_predictor)
    
    choice = self.choice.currentText()
    
    if choice == "C++逆引き":
        index_path = "/AI/LlamaIndex/index/index_C++逆引き.json"
    elif choice == "Python逆引き":
        index_path = "/AI/LlamaIndex/index/index_Python逆引き.json"
    else:
        index_path = self.input2.text()

    try:
        self.index = GPTSimpleVectorIndex.load_from_disk(save_path= index_path, service_context=service_context)
    except Exception as e:
        print('エラーが発生しました:', e)
        self.output.setText(str(e))
        self.box.setStyleSheet('background-color: #ff00ff')
        return
    else:
        self.box.setStyleSheet('background-color: #00ffff')
        
    self.output.setText("IDX読込完了")

[AI] LlamaIndexアプリ製作 その8 例外処理

[M1 Mac, Monterey 12.6.3, Python 3.10.4]

LlamaIndexアプリが簡単には落ちないよう例外処理を強化しました。

def makeIDX(self):
    # インデックスの作成および保存
    llm_predictor = LLMPredictor(llm=OpenAI(temperature=0, model_name="text-embedding-ada-002"))
    service_context = ServiceContext.from_defaults(llm_predictor=llm_predictor)
    
    data_path = self.input.text()
    data_path2 = data_path.replace("'", "") # 拡張子判定用
    data_path3 = Path(data_path2) # loader用

    if data_path2.endswith('.csv'):
        SimpleCSVReader = download_loader("SimpleCSVReader")
        loader = SimpleCSVReader()
    elif data_path2.endswith('.pdf'):
        PDFReader = download_loader("PDFReader")
        loader = PDFReader()
    else:
        print('ファイルがcsv,pdfではありません')
        self.output.setText("ファイルがcsv,pdfではありません")
        self.box.setStyleSheet('background-color: #ff00ff')
        return

    try:
        nodes = loader.load_data(file=data_path3)
    except Exception as e:
        print('エラーが発生しました:', e)
        self.output.setText(str(e))
        self.box.setStyleSheet('background-color: #ff00ff')
        return
    else:
        self.box.setStyleSheet('background-color: #00ffff')

    index = GPTSimpleVectorIndex.from_documents(nodes, service_context=service_context)
    
    now = datetime.datetime.now()
    formatted_time = now.strftime('%y%m%d_%H%M%S')

    index_file = "/AI/LlamaIndex/index/" + formatted_time + "_index.json"
    index.save_to_disk(index_file)
    
    self.input2.setText(index_file)
    self.idxBtn2.click()

[Python] 354 PyQt6でドラッグ&ドロップ

[M1 Mac, Monterey 12.6.3, Python 3.10.4]

PyQt6ではQLineEdit(FLTKにおけるFl_Input)にドラッグ&ドロップできるようにするには、QLineEditを継承したクラスを別途作成する必要があります。

機能が簡素なFLTKでもドラッグ&ドロップは標準装備されているのでこれは意外です。

from PyQt6.QtWidgets import QLineEdit

class MyLineEdit(QLineEdit):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setDragEnabled(True)
        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            for url in event.mimeData().urls():
                file_path = url.toLocalFile()
                self.setText(file_path)
            event.accept()
        else:
            event.ignore()

[AI] LlamaIndexアプリ製作 その7 C++とPythonの逆引きレファレンス化

[M1 Mac, Monterey 12.6.3, Python 3.10.4]

LlamaIndexアプリをC++やPyhonの逆引きレファレンスとして使えるようにしました。

読み込ませるインデックスファイルはコードの説明とコードの内容を対比させたCSVファイルをインデックス化したものです。C++は8行、Pythonはたった3行です。

インデックスファイルでこちらの求める回答形式を察してくれるので、言語の指定は不要です。

学習モデルの内容が2021年6月までですから、PyQt6については基本的には回答してくれないです。機嫌が良いと回答してくれることもあります。

全く別ジャンルの質問にも答えてくれます。専門ボットにもなれる単発質問対応AIといったところでしょうか。ChatGPTと比べて回答時間はかなり短いですが、コストはgpt-3.5-turboの10倍です。

Python用CSV