end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

setup Oracle Linux 9.1 for wsl2 on windows11

setup OracleLinux 8.7 for wsl on windows11 - end0tknr's kipple - web写経開発

先程の上記entryの修正版です。

先程のentryではsystemdを有効化する為、 genie ( https://github.com/arkane-systems/genie )をinstallしましたが、 以下のurlによれば、wsl version 2では systemdに対応しているそうです。

そこで、wsl1→2化した上で、Oracle Linux 9.1をセットアップしています。

目次

uninstall Oracle Linux 8.7

先程のentryで入れた Oracle Linux 8.7 をアンインストール

CMD> wsl --unregister OracleLinux_8_7

WSL 1→2化

ブラウザで https://aka.ms/wslstorepage へ、アクセスすると 以下のようにMicrosoft Storeが起動しますので、そこでインストール

CMD> wsl --version
WSL バージョン: 2.0.9.0
カーネル バージョン: 5.15.133.1-1
WSLg バージョン: 1.0.59
MSRDC バージョン: 1.2.4677
Direct3D バージョン: 1.611.1-81528511
DXCore バージョン: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows バージョン: 10.0.22621.2861

※ WSL ver.1では「--version」に対応しておらず、実行できません

install Oracle Linux 9.1

まず、install可能なdistributionを確認

CMD> wsl --list --online

インストールできる有効なディストリビューションの一覧を次に示します。
'wsl.exe --install <Distro>' を使用してインストールします。

NAME                                   FRIENDLY NAME
Ubuntu                                 Ubuntu
Debian                                 Debian GNU/Linux
kali-linux                             Kali Linux Rolling
Ubuntu-18.04                           Ubuntu 18.04 LTS
Ubuntu-20.04                           Ubuntu 20.04 LTS
Ubuntu-22.04                           Ubuntu 22.04 LTS
OracleLinux_7_9                        Oracle Linux 7.9
OracleLinux_8_7                        Oracle Linux 8.7
OracleLinux_9_1                        Oracle Linux 9.1
openSUSE-Leap-15.5                     openSUSE Leap 15.5
SUSE-Linux-Enterprise-Server-15-SP4    SUSE Linux Enterprise Server 15 SP4
SUSE-Linux-Enterprise-15-SP5           SUSE Linux Enterprise 15 SP5
openSUSE-Tumbleweed                    openSUSE Tumbleweed

Oracle Linux 9.1 のインストールと、ユーザ追加

CMD> wsl --install OracleLinux_9_1

Installing, this may take a few minutes...
Please create a default UNIX user account.
The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username: end0tknr
Changing password for user end0tknr.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
Installation successful!

systemd & sshd の有効化

/etc/wsl.conf を以下の内容で作成します。

※ wsl.conf の仕様は以下のurlが分かりやすいです

$ sudo vi /etc/wsl.conf

[boot]
systemd=true

Oracle Linuxを再起動すると、systemdの起動を確認できます

CMD> wsl --terminate OracleLinux_9_1
CMD> wsl -d OracleLinux_9_1

$ ps -ef
UID   PID  PPID  C STIME TTY  TIME CMD
root    1     0  0 07:16 ?    00:00:00 /sbin/init
root    2     1  0 07:16 ?    00:00:00 /init
<略>
root   30     1  0 07:18 ?    00:00:00 /usr/lib/systemd/systemd-journald
<略>

最後にsystemctlでsshdを有効化します

$ sudo systemctl enable sshd
$ sudo systemctl start  sshd

IPアドレスの固定

wsl上のoracle linuxはdefaultでは起動する度にipアドレスが変更され、 sshやsmbでの接続が手間ですので、固定します。

まず、oracle linux側で割当てられているipを確認

$ ip a
<略>
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP>
   mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:f4:52:da brd ff:ff:ff:ff:ff:ff
    inet 172.18.129.236/20 brd 172.18.143.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::215:5dff:fef4:52da/64 scope link
       valid_lft forever preferred_lft forever

次に、power shellを管理者モードで起動し、 vEthernet (WSL)の ifIndex を確認した上で、固定ipを設定。

参考url

PS> Get-NetAdapter -IncludeHidden

Name                      InterfaceDescription                    ifIndex <略>
----                      --------------------                    -------   :
ローカル エリア接続* 7    WAN Miniport (PPPOE)                         22 <略>
vEthernet (WSL (Hyper-... Hyper-V Virtual Ethernet Adapter             24 
<略>
vSwitch (WSL (Hyper-V ... Hyper-V Virtual Switch Extension Ada...      10 <略> 
<略>
PS> New-NetIPAddress -IPAddress 172.18.129.236 -PrefixLength 24 -InterfaceIndex 24

IPAddress         : 172.18.129.236
InterfaceIndex    : 24
InterfaceAlias    : vEthernet (WSL (Hyper-V firewall))
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Manual
SuffixOrigin      : Manual
AddressState      : Tentative
ValidLifetime     :
PreferredLifetime :
SkipAsSource      : False
PolicyStore       : ActiveStore

IPアドレス固定の自動化

先程、固定したipはpcの停止時に無効化されますので、 ps1ファイルとタスクスケジューラでip固定の自動化を行います

CMD> vi c:/Users/end0t/local/AddIPAddress.ps1

New-NetIPAddress -IPAddress 172.18.129.236 -PrefixLength 24 -InterfaceIndex 24

プログラムスクリプト powershell.exe
引数の追加 -ExecutionPolicy Bypass c:\Users\end0t\local\AddIPAddress.ps1
開始 空欄

install samba

$ sudo yum install samba
$ sudo systemctl enable smb
$ sudo systemctl start  smb

$ sudo pdbedit -a end0tknr
new password:
retype new password:
Unix username:        end0tknr
NT username:
Account Flags:        [U          ]
User SID:             S-1-5-21-3605739558-1094150744-591740496-1000
Primary Group SID:    S-1-5-21-3605739558-1094150744-591740496-513
Full Name:
Home Directory:       \\A64-WSL\end0tknr
HomeDir Drive:
Logon Script:
Profile Path:         \\A64-WSL\end0tknr\profile
Domain:               A64-WSL
<略>

OracleLinuxの停止

CMD> wsl --terminate OracleLinux_8_7

CMD> wsl --list --verbose
  NAME               STATE           VERSION
* OracleLinux_8_7    Stopped         2

setup OracleLinux 8.7 for wsl on windows11

wsl(Windows Subsystem for Linux)にredhat系であるOracleLinuxが あることを知りましたので、お試し。

※ 2024/1時点で、OracleLinux9もwslに対応していますが、 systemctlが依存する .net runtimeが見当たりませんでしたので、 今回、OracleLinux 8.7を使用しています

目次

参考url

wsl対応済 linux distribution 確認

コマンドプロンプトで「wsl --install」を実行することで確認できます

CMD> wsl --install
Linux 用 Windows サブシステムは既にインストールされています。.

インストールできる有効なディストリビューションの一覧を次に示します。
'wsl --install -d <Distro>' を使用してインストールします。

NAME                                   FRIENDLY NAME
Ubuntu                                 Ubuntu
Debian                                 Debian GNU/Linux
kali-linux                             Kali Linux Rolling
Ubuntu-18.04                           Ubuntu 18.04 LTS
Ubuntu-20.04                           Ubuntu 20.04 LTS
Ubuntu-22.04                           Ubuntu 22.04 LTS
OracleLinux_7_9                        Oracle Linux 7.9
OracleLinux_8_7                        Oracle Linux 8.7
OracleLinux_9_1                        Oracle Linux 9.1
openSUSE-Leap-15.5                     openSUSE Leap 15.5
SUSE-Linux-Enterprise-Server-15-SP4    SUSE Linux Enterprise Server 15 SP4
SUSE-Linux-Enterprise-15-SP5           SUSE Linux Enterprise 15 SP5
openSUSE-Tumbleweed                    openSUSE Tumbleweed

install OracleLinux 8.7 for wsl

CMD> wsl --install -d OracleLinux_8_7

↑こう実行すると、↓この別windowが表示され、ID/PWを設定し、完了

Installing, this may take a few minutes...
Please create a default UNIX user account.
The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username: end0tknr
Changing password for user end0tknr.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
Installation successful!

install済みlinux distribution 確認

CMD> wsl --list --verbose
  NAME               STATE           VERSION
* OracleLinux_8_7    Stopped         2

install済みlinux distribution 起動

以下のコマンドを実行すると、OracleLinuxが起動し、 プロンプトの表示が変更されます

CMD> wsl -d OracleLinux_8_7
$

genie による systemd & sshd自動起動

OracleLinuxにはsshdが含まれていますが、 defaultではsystemctl自動起動しません。

$ sudo systemctl start sshd
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

どうやら defaultではsystemctlのdaemon自体が起動していないようですので、 OracleLinux内でrpmを追加installします。

$ wget https://github.com/arkane-systems/genie/releases/download/v1.44/genie-1.44-1.fc34.x86_64.rpm
$ wget https://download-ib01.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/d/daemonize-1.7.8-1.el8.x86_64.rpm

$ sudo yum install daemonize-1.7.8-1.el8.x86_64.rpm
$ sudo yum install genie-1.44-1.fc34.x86_64.rpm

次に、installした genie の初期化と実行を行います

genieの他のoptionは「genie --help」でご確認ください。

$ genie --shell
Waiting for systemd....!!!!!<略. 数分、待ちます> 

【TODO】「genie -s」自体の自動実行は今後調査

ここまでで、systemdが起動していますので、改めてsshd自動起動を設定します

$ sudo systemctl enable sshd
$ sudo systemctl start  sshd

OracleLinuxのipアドレス確認

以下の通りですので、sshでの接続にご利用ください

$ ip a
<省略>
6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP>
   mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:23:48:b0 brd ff:ff:ff:ff:ff:ff
    inet 172.27.92.9/20 brd 172.27.95.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::215:5dff:fe23:48b0/64 scope link
       valid_lft forever preferred_lft forever

install samba

$ sudo yum install samba
$ sudo systemctl enable smb
$ sudo systemctl start  smb

$ sudo pdbedit -a end0tknr
new password:
retype new password:
Unix username:        end0tknr
NT username:
Account Flags:        [U          ]
User SID:             S-1-5-21-3605739558-1094150744-591740496-1000
Primary Group SID:    S-1-5-21-3605739558-1094150744-591740496-513
Full Name:
Home Directory:       \\A64-WSL\end0tknr
HomeDir Drive:
Logon Script:
Profile Path:         \\A64-WSL\end0tknr\profile
Domain:               A64-WSL
<略>

OracleLinuxの停止

CMD> wsl --terminate OracleLinux_8_7

CMD> wsl --list --verbose
  NAME               STATE           VERSION
* OracleLinux_8_7    Stopped         2

Windows11 proで WSL (Windows Subsystem for Linux)を有効化

インターネットで検索して表示される WSLの有効化方法は、 同じWindows11であってもサイトによって内容が異なります。

この異なる理由は不明ですが、私が使用している Windows11 pro on thinkpad x11 では 「システム > オプション機能 > Windowsのその他の機能」にある 「LinuxWindowsサブシステム」で有効化できました

power shellによるwindowsのprocess検索をpython経由で実施

rpa用にpywinautoを使用していたせいか、 windowsのあるプロセスが起動済みであることを pywinauto.findwindows.find_windows()で確認していましたが、 プロセスが起動済みであるにも関わらず、 find_windows()できないケースがあり、 pywinautoでは解消できない気がしましたので、 以下のように、powershellのGet-Process を使用するようにしてみました。

これまでのNGな例

import pywinauto

def find_xerial_win():
    func_name = sys._getframe().f_code.co_name
    win_name =".*XERIAL.*"
    
    try:
        find_win = \
        lambda: pywinauto.findwindows.find_windows(title_re=win_name)[0]
        time.sleep(2)
        dialog = pywinauto.timings.wait_until_passes(5, 1, find_win)
        time.sleep(2)
    except Exception as e:
        logger.error("fail %s %s %s",func_name,win_name,e)
        return None

    if not dialog:
        logger.warning("fail %s %s, dialog is empty.",func_name,win_name)
        return None

    return True

今回のOKそうな例

import subprocess

def find_xerial_process():
    func_name = sys._getframe().f_code.co_name

    process_name ="xerial"
    powershell_cmd = 'powershell "Get-Process -Name %s"' % (process_name)
    
    try:
        process = subprocess.Popen(powershell_cmd,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE,
                                   shell=True)
        stdout, stderr = process.communicate()
        stdout = stdout.decode('utf-8')

    except Exception as e:
        logger.error("fail %s %s %s",func_name,process_name,e)
        return None

    if not process_name in stdout:
        logger.error("fail %s %s in %s",func_name,process_name,stdout)
        return None

    return True

障害/災害対応時のクロノロジー (chronology、略して クロノロ)

クロノロ・クロノロジーとは

クロノロジー( chronology )略して「クロノロ」は、障害や災害の際
本部や各チームなどが起こった出来事、収集した情報、発信した情報について
「誰が発信し」「誰が受け」「どのような内容であったか」を
時系列に記録していくもの

らしい。

この用語の存在から知りませんでした

以下は、徳島県 半田病院のでのクロノロ例です

https://img.logmi.jp/article_images/7aRABmGSPfRnDQNbKxxCp8.png

参考url

https://bigfjbook.com/chronology/

マイクロソフト WORDに付属の「読みやすさの評価機能」

ms wordにこのような機能が付属していることに驚きました。

以下の手順で利用するようですが、 過度な期待はしない方がよさそうです。

step 1 - オプションで「文書の読みやすさを評価する」をON

step 2 - 「校閲」から「スペルチェックと文章校正」を実行

LLM LangChain Retrieval (旧Indexes) オレオレ入門

LLM LangChainへ、これから入門 - end0tknr's kipple - web写経開発

更に上記entryの続き。

本日時点で、LangChain Retrieval の中では VectorstoreIndexCreator が楽な気がします。

参考url

LangChain Retrievalとは?【Document Loaders・Vector Stores・Indexing etc.】

LangChain Retrieval (旧Indexes)とは

  • 2023時点で Retrievalというmodule名ですが、以前は Indexes
  • CSVやPDF等、LLM外部にある独自dataを用いた回答生成が可能
主要機能 内容
Document Loaders PDFやCSV等のdataを読込み
Document transformers Text Splitters等、読込みdataをLLMが扱う形に変換
Text embedding models textを数値ベクトルに変換
Vector stores ベクトル化されたdataを管理
Retrievers 長いtextを複数documentの塊に分割し検索
Indexing 大量textを効率的検索の為、整理,構造化

LangChain Retrieval + OpenAI 使用例

0. pip installと api key設定

!pip install langchain
!pip install openai
import os
os.environ['OPENAI_API_KEY'] = 'sk-ないしょ'

1. Document Loaders - PDF

!pip install pypdf
!pip install tiktoken
!pip install faiss-cpu
from langchain.document_loaders  import PyPDFLoader
from langchain.vectorstores      import FAISS
from langchain.embeddings.openai import OpenAIEmbeddings

pdf_url = 'https://blog.freelance-jp.org/wp-content/uploads/2023/03/FreelanceSurvey2023.pdf'
loader = PyPDFLoader(pdf_url)
pages = loader.load_and_split()

# print(pages[0])

faiss_index = FAISS.from_documents(pages,OpenAIEmbeddings())

prompt = '「フリーランスのリモートワークの実態」について教えて、'
docs = faiss_index.similarity_search(prompt,k=2)
for doc in docs:
  print( str(doc.metadata['page']) , ':', doc.page_content )

↑こう書くと、↓以下のように質問文であるpromptに関連するページが表示されます

44 : フリーランスのリモートワーク実態  (1/3)
45(n=850)Q.リモートワークの実施およびその影響に関して、
それぞれ当てはまる選択肢を一つ選んでください。
(単一回答)
 ※リモートワークとは、情報通信技術 (ICT)を活用した、
 場所や時間にとらわれない柔軟な働き方のことを指します。
 <略>

2. Text Splitters ( Document transformers )

from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
    separator     = "。",
    chunk_size    = 50,      # 分割する際の最大size
    chunk_overlap = 0,
)
long_txt = '''
吾輩は猫である。名前はまだない。どこで生れたか頓(とん)と見当がつかぬ。
何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。
しかもあとで聞くとそれは書生という人間中で一番獰悪(どうあく)な種族であったそうだ。
この書生というのは時々我々を捕(つかま)えて煮て食うという話である。
しかしその当時は何という考(かんがえ)もなかったから別段恐しいとも思わなかった。
'''
txts = text_splitter.split_text(long_txt)
print(txts)

# documentというclassの塊に分割する場合、create_documents()
# doc_txts = text_splitter.create_documents([long_txt])
# print(doc_txts)

↑こう書くと、↓こう表示されます。

※ 「separator="。"」の指定で必ず分割される訳でなく、 「chunk_size=50」に近い長さで分割するみたい。

※「Created a chunk of size 51」のwarningの意味は調べていません

WARNING:langchain.text_splitter:Created a chunk of size 51,
which is longer than the specified 50
['吾輩は猫である。名前はまだない。どこで生れたか頓(とん)と見当がつかぬ',
 '何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している',
 '吾輩はここで始めて人間というものを見た',
 'しかもあとで聞くとそれは書生という人間中で一番獰悪(どうあく)な種族であったそうだ',
 'この書生というのは時々我々を捕(つかま)えて煮て食うという話である',
 'しかしその当時は何という考(かんがえ)もなかったから別段恐しいとも思わなかった',
]

3. Vector stores

!pip install chromadb
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter     import CharacterTextSplitter
from langchain.vectorstores      import Chroma
from langchain.indexes           import VectorstoreIndexCreator
from langchain.document_loaders  import TextLoader

long_txt = '''
吾輩は猫である。名前はまだない。どこで生れたか頓(とん)と見当がつかぬ。
何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。
しかもあとで聞くとそれは書生という人間中で一番獰悪(どうあく)な種族であったそうだ。
この書生というのは時々我々を捕(つかま)えて煮て食うという話である。
しかしその当時は何という考(かんがえ)もなかったから別段恐しいとも思わなかった。
'''
text_splitter = CharacterTextSplitter(
    separator     = "。",
    chunk_size    = 50,
    chunk_overlap = 0)
index = VectorstoreIndexCreator(
    vectorstore_cls= Chroma,             # default Vectorstore class
    embedding      = OpenAIEmbeddings(), # default Embedding class
    text_splitter  = text_splitter       # text splitter class
   ).from_documents( text_splitter.create_documents([long_txt]) )
   
answer = index.query('吾輩は何ですか?')
print(answer)

↑こう書くと、↓こう表示されます。

 吾輩は猫です。

先程、「Vector stores=ベクトル化されたdataを管理」と記載しましたが、 VectorstoreIndexCreator がvectorstore_cls等を引数に受け取り、 様々さばいてくれますので、上記のように回答を得ることができます。

4. Retrievers

from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter     import CharacterTextSplitter
from langchain.vectorstores      import Chroma
from langchain.vectorstores      import FAISS

long_txt = '''
吾輩は猫である。名前はまだない。どこで生れたか頓(とん)と見当がつかぬ。
何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。
しかもあとで聞くとそれは書生という人間中で一番獰悪(どうあく)な種族であったそうだ。
この書生というのは時々我々を捕(つかま)えて煮て食うという話である。
しかしその当時は何という考(かんがえ)もなかったから別段恐しいとも思わなかった。
'''

text_splitter = CharacterTextSplitter(
    separator     = "。",
    chunk_size    = 50,
    chunk_overlap = 0)
docs = text_splitter.create_documents([long_txt])
db = FAISS.from_documents(docs,OpenAIEmbeddings())

retriever = db.as_retriever() # retriever objectの作成

# 関連documentを検索
ans_docs  = retriever.get_relevant_documents('吾輩は何ですか?')

print( ans_docs[0] )

↑こう書くと、↓こう表示されます

page_content='吾輩は猫である。名前はまだない。どこで生れたか頓(とん)と見当がつかぬ'

LLM LangChain Model I/O のオレオレ入門

LLM LangChainへ、これから入門 - end0tknr's kipple - web写経開発

先程の上記entryの続き

参考url

LangChain Model I/Oとは?【Prompts・Language Models・Output Parsers】

対応model 3グループ

内容
LLMs 例えば、GPT3.5(text-davinci-003)、Flan-T5(flan-t5-xl)
Chat Models LLMsを用い、チャットに特化。gpt-3.5-turbo、gpt-4
Text Embedding Models 類似度計算等に用いる文章のベクトル化。

LLMs と Chat Models の違い

LLMs 単一の文字列(prompt)を受取り、文字列を出力(補完)
Chat models 複数のチャットメッセージを受取り、メッセージを出力

上記の通りで、以降に記載する具体的な使用方法と併せて、ご確認ください。

LangChain Model I/O + OpenAI 使用例

以下の通りですが、参考urlの内容が丁寧にまとめられていますので、 そちらの方が参考になります

0. pip installと api key設定

!pip install langchain
!pip install openai
import os
os.environ['OPENAI_API_KEY'] = 'sk-ないしょ'

1. LLMs の使用例

from langchain.llms import OpenAI

llm = OpenAI(model_name='text-davinci-003')
llm('哲学とはどのような学問ですか?')

↑こう書くと、↓こう表示されます

哲学とは、
人間が生きる上で必要な基礎的な知識や考えを追求する学問のことです。
哲学は、科学、宗教、歴史、政治などの専門的な学問領域を超えて、
倫理的な基準や価値観を検討する学問であり、
人間自身の目的や意義を探求する学問でもあります。```

2. Chat Models の使用例

from langchain.chat_models import ChatOpenAI
from langchain.schema      import SystemMessage,HumanMessage

chat = ChatOpenAI(model_name='gpt-3.5-turbo')

chat([SystemMessage(content='日本語で回答してください'),
      HumanMessage( content='哲学とはどのような学問ですか?')])

↑こう書くと、↓こう表示されます

AIMessage(content='哲学は、人間や世界の根本的な問いについて考える学問です。
それは、存在の意味や目的、真理や知識の性質、倫理や道徳の原則などについての
理論的な探求を通じて、人間の思考や実践について深く考えることを目的としています。
哲学は、一般的な問題や概念に対する批判的な分析を行い、
論理的な思考や論証を通じて真理や知識に迫ることを特徴としています。
<略>

3. Text Embedding Models の使用例

!pip install tiktoken
from langchain.embeddings import OpenAIEmbeddings

embeddings = OpenAIEmbeddings()
query_result = embeddings.embed_query('哲学とはどのような学問ですか?')

print(query_result)

↑こう書くと、↓こう表示されます

[0.023728431990641022, -0.004893595788907291, 0.017749119442909876, -0.01824005123399546,
-0.019033098478528198, 0.0007367929748512503, -0.019461091490400973, 0.0007210579308020852,
-0.015747623423104453, -0.01272020201906606, -0.005843991844117188, 0.003071478782318001,
0.01855475258064004, -0.012336267083964817, <略>]

OpenAI API利用時「RateLimitError: Error code: 429 」エラー

久しぶりに OpenAI API を利用したところ、以下のエラー

RateLimitError: Error code: 429 -
{'error': {
  'message':
    'You exceeded your current quota,
     please check your plan and billing details.
     For more information on this error,
   read the docs:
     https://platform.openai.com/docs/guides/error-codes/api-errors.',
  'type' : 'insufficient_quota',
  'param': None,
  'code' : 'insufficient_quota'}}
  ```

以前は https://platform.openai.com/api-keys にてAPI KEYを発行し、 無料枠で使用していましたが、どうやら、支払情報の設定が必要らしく https://platform.openai.com/account/billing/overview にて、以下のように修正し、解消。

LLM LangChainへ、これから入門

これからLangChainを始めるにあたり、メモ

参考url

LangChainの概要と使い方|サクッと始めるプロンプトエンジニアリング【LangChain / ChatGPT】

LLM LangChainの概要

GPT等のLLMを機能拡張する為のライブラリ

機能 内容
Model I/O 様々なLLMの組合せ
Retrieval (Indexes) 外部独自dataを用いた回答生成
Chains 連続したプロンプトを入力&実行
Memory ChainsやAgentsの内部状態を保持
Agents LLM自体による次のactionを決定,実行繰返し
Callbacks LLMののログや非同期処理等の管理

Llamaindexとの違い

Lllamaindexは独自データを使ったQAチャットを作成できるライブラリ。 内部的にはLangchainを使用。

LLM Transformer オレオレ要約

使ってはいるものの、内容を理解していないので、メモ

参考url

Transformer の概要

EncoderとDecoderで構成され、内部にあったRNN層を除き、 Attention層のみで構成することで「速度、精度、汎用性」が向上

Transformer のLLM例

LLM ベース 使用例
Bert (google製) Encoder テキスト分類、文章の要約
GPT (openai製) Decoder 文章生成、質疑応答

Transformer の構成

  • EncoderとDecoderはそれぞれ単独利用もOK。
  • DecoderのAttention層はEncoder入力を処理するもので、Decoderのみ使用する場合,不要
  【Encoder】             【Decoder】
                          Output      
                          Probablities
                              ↑
┌──────┐        ┌──┴───┐
│Attention層 ├───→│Attention層 │
└──────┘        └──────┘
      ↑                      ↑
      │                ┌──┴───┐
      │                │Masked      │
      │                │Attention層 │
      │                └──────┘
      │                      ↑
┌──┴───┐        ┌──┴───┐
│単語位置把握│        │単語位置把握│
└──────┘        └──────┘
      ↑                      ↑        
  Inputs                  Outputs
構成要素 役割
Encoder テキストの意味表現を固定長数値ベクトル化
Decoder 意味表現ベクトルから翻訳後のテキスト生成
Attention層 文中で重要な単語に重み付け
Masked Attention層 ググった方が早いと思います

Hugging Face Transformers Pipelines の日本語文章生成の練習

これまで利用したことがありませんでしたので、google colab で練習

目次

参考url

pip install

!pip install transformers
!pip install sentencepiece

sentencepiece (Tokenizer)とは

SentencePiece 入門|npaka によれば

「SentencePiece」は、テキストを「サブワード」に分割するツールです。

「自然言語処理」の深層学習を行うには、テキストを何かしらの「トークン」に分割し、
それを「ベクトル表現」に変換する必要があります。

以前は、「MeCab」の形態素解析を使ってテキストを「単語」に分割するのが一般的でした。
しかし「単語」を使うのは実用上の問題点があります。語彙数が膨大になり、
高頻度語彙のみに限定したとしても、低頻度語彙が捨てられ未知語として
扱われることになります。

「SentencePiece」では「サブワード」を使ってこの問題を解決しています。
はじめに、テキストを単語に分割し、各単語の頻度を求めます。
次に、高頻度単語は1語彙として扱い、低頻度単語はより短い語彙に分割します。
そして、語彙数が事前に指定した数になるまで、分割を繰り返します。
これによって、語彙数を小さくしつつ、未知語をなくすことを可能にしています。

らしい

Pipelines python script

from transformers import pipeline, set_seed
# https://huggingface.co/docs/transformers/main_classes/pipelines
# https://huggingface.co/gpt2
# https://huggingface.co/rinna/japanese-gpt2-small
# generator = pipeline('text-generation', model='gpt2')
generator = pipeline('text-generation', model='rinna/japanese-gpt2-small')
set_seed(42)
generator("東京都国分寺市は、", max_length=30, num_return_sequences=5)
#generator("Hello, I'm a language model,", max_length=30, num_return_sequences=5)

↑こう書くと、↓こう表示されます

Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.
[{'generated_text': '東京都国分寺市は、埼玉県における人口で2番目に多い自治体である。 国分寺市の市域面積が1. 0平方キロメートルであるが、埼玉県では、'},
 {'generated_text': '東京都国分寺市は、東京都のほぼ中央に位置し、都と市の中間に位置する。 また国分寺市内には、jr東日本中央線や東北本線が通る。'},
 {'generated_text': '東京都国分寺市は、市内の市町村と政令指定都市の市町との合併による市町村合併による市制移行が行われた。 国分寺市は、東京都の多摩'},
 {'generated_text': '東京都国分寺市は、全国に先駆けて市制を施行し、1971年(昭和46年)5月1日市制施行となりました。これは1975年('},
 {'generated_text': '東京都国分寺市は、東京23区内において、国分寺市議会による地方自治憲章(政憲議会定例会において議長1名の選出権限をもつ'}]
 

Pipelines を使用しない python script

先程のPipelinesは、1行で様々、処理してくれますが、 同様処理内容は、以下のように記載することもできます。

from transformers import AutoTokenizer, AutoModelForCausalLM

tokenizer = AutoTokenizer.from_pretrained("rinna/japanese-gpt2-small", use_fast=False)
tokenizer.do_lower_case = True  # due to some bug of tokenizer config loading

model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt2-small")

prompt = "東京都国分寺市は、"
# return_tensors='pt'により pytorchのtensor型でtokenize
prompt_ids = tokenizer(prompt, return_tensors='pt').input_ids
outputs = model.generate(prompt_ids,
                         do_sample=True,
                         max_length=30,
                         num_return_sequences=5,
                         repetition_penalty=1.1)
tokenizer.batch_decode(outputs,skip_special_tokens=True)

↑こう書くと、↓こう表示されます

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.
A decoder-only architecture is being used, but right-padding was detected! For correct generation results, please set `padding_side='left'` when initializing the tokenizer.
['東京都国分寺市は、多摩地域の中核都市として昭和40年(1965年)1月に市制施行された。 その後、市内を鉄道路線によって結び',
 '東京都国分寺市は、国分寺市内を南北に走る「国分寺道」が有名で、 国分寺駅 の南口から北口にかけては、',
 '東京都国分寺市は、平成17年(2005)度から、 都市政策学部が「地方独立行政法人多摩センター」に名称変更されたことに伴い、',
 '東京都国分寺市は、鎌倉時代末期に鎌倉よりの町としての町として誕生する。 長禄元年(1229年)源頼朝と',
 '東京都国分寺市は、新宿・江戸川地域からさらに近いことから、国分寺の城下町が広がりました。また、国分寺には古墳などが多く']

六法のメモ

報道等で耳にしますが、定義を答えられなかったので、メモ

六法の種類

日本国憲法 |国のしくみや理想
刑法 犯罪に関するルールと裁判の手続き
刑事訴訟法
民法 日常生活に関するルールと裁判の手続き
民事訴訟
商法 商売に関するルール

刑法 - 刑罰の種類

死刑 死刑は、受刑者の生命を奪う刑です。
懲役刑 有期刑と無期刑があり、有期は1ヶ月~20年。強制労動もあり
禁錮 懲役刑のような強制労動なし
拘留 1日~ヶ月で、強制労動なし
罰金刑 1万円以上。支払えない場合、労役場で日当換算の労務
科料 千円~1万円。支払えない場合、罰金刑と同様
没収 死刑~懲役刑~科料の主刑に対しての附加刑

厚生省によるセキュリティ教育支援ポータルサイトと医療情報システムの安全管理に関するガイドライン

IPAがこの種のコンテンツを公開することは理解しますが、 厚生労働省がこのようなコンテンツを大量に公開していることに驚きました。

厳しい経営の中、情報セキュリティに予算や人材を回せず、 脆弱な医療機関が多くあることが背景にあるのだと、勝手に想像します。

svg アニメーションの練習 - transparent と scale()

https://end0tknr.hateblo.jp/entry/20231211/1702260505

先日、上記entryで、cssによるテキストアニメーションを行いましたが、 今回は、svg アニメーション

その1 - 透過 (transparent)により、全体を徐々に表示

<svg width="800" height="300" xmlns="http://www.w3.org/2000/svg">
<style>
.stop_21, .stop_22 { animation-name           : grad_2_anime;
             animation-delay          : 0.0s;
             animation-duration       : 4s;
             animation-iteration-count: infinite;
             /* ease-out : アニメーション終了付近で動きが緩やか */
             animation-timing-function: ease-in-out;
           }
@keyframes grad_2_anime { 0%   { stop-color: transparent;   }
              100% { stop-color: '';            }}
#cone_2 { fill : url(#grad_2);}
</style>
  <defs>
    <!-- y1=y2=0%で横方向グラデーション定義 -->
    <linearGradient id="grad_2" x1="0%" y1="0%" x2="100%" y2="0%">
      <!--始点(0%) -->
      <stop class="stop_21" offset="0%"   style="stop-color:#00f;stop-opacity:0"/>
      <!--終点(100%) -->
      <stop class="stop_22" offset="100%" style="stop-color:#00f;stop-opacity:1"/>
    </linearGradient>
  </defs>
  
  <!-- 小文字のqは相対座標指定による2次ベジェ曲線 -->
  <path id="cone_2"
    d="M0,0 q50,100 600,100 l0,30 q-550 0 -600 100 z"/>
</svg>

その2 - scaleX()により、端から徐々に表示

今回の不確実性コーンは pathで描いていますが、 pathには、scale()が機能しないようですので、 別途用意したrectでマスクし、このrectのサイズを徐々に小さくしています。

<svg width="800" height="300" xmlns="http://www.w3.org/2000/svg">
<style>
#cone_3 { fill : url(#grad_3);}
#screen_3 { animation-name           : screen_open;
        animation-delay          : 0.0s;
        animation-duration       : 4s;
        animation-timing-function: ease-in-out;
        animation-iteration-count: infinite;
        fill            : #fff;
        transform-origin: 600px 0; }
@keyframes screen_open {
  0%   { transform: scaleX(1); }
  100% { transform: scaleX(0); }
}
</style>
  <defs>
    <!-- y1=y2=0%で横方向グラデーション定義 -->
    <linearGradient id="grad_3" x1="0%" y1="0%" x2="100%" y2="0%">
      <!--始点(0%) -->
      <stop class="stop_31" offset="0%"   style="stop-color:#00f;stop-opacity:0"/>
      <!--終点(100%) -->
      <stop class="stop_32" offset="100%" style="stop-color:#00f;stop-opacity:1"/>
    </linearGradient>
  </defs>
  
  <!-- 小文字のqは相対座標指定による2次ベジェ曲線 -->
  <path id="cone_3"
    d="M0,0 q50,100 600,100 l0,30 q-550 0 -600 100 z"/>
  <rect id="screen_3" x="0" y="0" width="600" height="230"/>
</svg>