"LGPL and Java"を読んだ

JavaというかJVMを使わないといけないような気がしていて、Javaの場合にLGPLがどう働くのかが気になっていた。 LGPL and Javaを読んでみた。 今まで気にしたことはなかったが、www.gnu.orgの文書は、基本的にはCreative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND)でライセンスされているようだ。 と言うことで、読むためにほぼ全訳したメモはあるのだが、それを公開することはできなさそうだ。

ただ、私の知りたいことをまとめると、以下の2点になりそうで、それを書いておくのは問題ないだろう。

  • LGPLは、オブジェクト指向言語の継承を、Cの関数呼び出しと同様に扱う。
  • LGPLでライセンスされたJavaライブラリーをJARファイルとして扱う時は、ダイナミックリンクと同様に考えて良い。

個人番号カード(マイナンバーカード)を健康保険証として利用する場合の暗証番号は、利用者証明用電子証明書用の暗証番号だった

そろそろ健康保険証としてマイナンバーカードを使い始めてみようとしたのだが、ディジタル庁の説明を見ても 「4桁の暗証番号入力」としか書かれていないので、署名用電子証明書用、利用者証明用電子証明書用、券面事項入力補助用、住民基本台帳用と4種類ある暗証番号やパスワードのいずれを入力 するのかが全く書かれていないようだ。まあ、「4桁の」ということで、署名用電子証明書用のパスワードではないのは分かる。おそらく利用者証明用電子証明書用だろうとは漠然と思っていた。 実際に使ってみると、確かに利用者証明用電子証明書用の暗証番号を入力すれば利用できた。

厚生労働省の「よくある質問~マイナ保険証について~ 令和6年7月版」には直接的ではないが、ちゃんと書かれていた。

もし、暗証番号を忘れたり、ロックされている場合は、住民票のある市区町村窓口等に行って利用者証明用電子証明書パスワード(4桁の暗証番号)の再設定が必要になります。

3つ設定値があれば3つ別々に設定するに決まっているので、ちゃんとどの暗証番号か明示して説明して欲しい。 端末の画面でも単に「暗証番号」としか表示されていなかった。

Data General softwareのhobbyist license

Data generalの製造していたNovaやEclipseEclipse MVAViiONで動くソフトウェアが、"License Agreement for Hobbyist and Non-Commercial Use of DG Software"というライセンスで公開されている。 このライセンスでカバーされている訳ではないようだが、NovaやEclipseのソフトウェアハードウェアAViiONなどのドキュメンテーションも公開されている。

この"License Agreement for Hobbyist and Non-Commercial Use of DG Software"を読むと、このソフトウェアを、個人的なオープンソースなエミュレーターを作成するのに使うようなことも許されるようだ。

Amazon Kindle Fireタブレットで、放送大学の学生向けのインターネット配信を視聴する

放送大学では学生向けには、テレビで放送されている講義のビデオと、ラジオで放送されている講義のオーディオがウェブ上で配信されている。 これはどうやら、Widevine CDMを使っているようだ。 そして、ウェブブラウザーのuser agent stringを見て視聴できるかチェックしている。

私は手元にAmazon Fire Tabletを持っているので、これで視聴したいのだが、標準で搭載されているAmazon Silkウェブブラウザーでは視聴することができない。 また、https://ftp.mozilla.org/pub/fenix/releases/からFirefox for Androidの.apkファイルをダウンロードしてインストールすることもできるが、このFirefox for Androidもサポートされておらず、視聴することができない。

しかし、最近のFirefox for Androidではextensionを使うことができる。extensionには、user agentの切り替えをするものも存在している。 User-Agent Switcher by Erin SchlarbはFirefox for Androidで利用でき、 これで「Android Phone / Chrome 126」にすると、無事に視聴することができた。

Windows 10 Proで、ChromiumベースなMicrosoft Edgeを削除する

ドメインに参加している場合には、ChromiumベースなMicrosoft Edgeのバージョンアップを止めることはできるのだが、そうでないと止めることはできないようである。 と言うことで、クリーンインストールしていると、ドメイン参加前に勝手に最新版(今日であれば126)に更新されてしまうことがある。 Microsoft Edgeを削除する簡単な方法がないし、古いバージョンに戻せる簡単な方法もなく困っていた。

https://github.com/ShadowWhisperer/Remove-MS-EdgeにあるRemove-Edge_GUI.exeを使ったところ、確実に削除することができた。 ドメインに参加した上で、Remove-Edge_GUI.exeで削除し、求めるバージョンのインストーラーでインストールすれば良い。

NetBSD/amd64でllama.cppを使ってみる

はじめに

生成AIが私の知りたいことに答えてくれたことはないのだが、手元の端末のみで動くのであれば、遊ぶのには良いかもしれない。 pkgsrcには含まれていないが、pkgsrc-wipには、llama.cppが含まれている。 llama.cppのうち、C++で書かれた部分は正常にビルドでき、動くようである。 モデルのフォーマットを変換するためのPythonスクリプトは、 いろいろと現在のpkgsrcに含まれていないパッケージが必要であり動かない。 ただ、現在のllama.cppで扱うことのできるGGUF形式のモデルファイルをそのままダウンロードすることができるので、 使ってみるには、Pythonスクリプトは不要である。

どのモデルが動かせるか?

ChatGPTのようなチャットのできるモデルを使ってみたいと考えている。 動かそうとしているPCは、CPUとしてAMD Ryzen 7 5800Uを搭載した RAM 16GBのHP Envy 13である。

用意されているLLaMA 2のモデルでは、70B Q8_0のモデル(llama-2-70b-chat.Q8_0.gguf)が最大であるようだった。 これは、 https://huggingface.co/TheBloke/Llama-2-70B-Chat-GGUF によると、76GB程度のRAMが必要ということなので、到底利用することはできない。

13B Q8_0のモデル(llama-2-13b-chat.Q8_0.gguf)は、 https://huggingface.co/TheBloke/Llama-2-13B-chat-GGUF によると、16GB程度のRAMが必要とのことで、 試してみたが、スラッシングを起こして、動作が非常に緩慢であり実用できなかった。

と言うことで、 https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF にあるRAMを 7GB弱利用する7B Q4_K_Mのモデル(llama-2-7b-chat.Q4_K_M.gguf)を試してみると 実用的な速度で動作させることができた。 このモデルは「medium, balanced quality - recommended」とされている。

モデルを動かす準備をする

llama.cppをビルドするには、以下のようにすれば良い。

# cd /usr/pkgsrc/wip/llama.cpp
# make install

これで、/usr/pkg/bin/llama-cliというコマンドがインストールされる。

また、自分のホームディレクトリーに、llama.cpp用の作業用ディレクトリーを用意し、 その中に必要なものを置くようにする。

$ mkdir -p ~/llama.cpp/models
$ cd ~/llama.cpp/models
$ ftp https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q4_K_M.gguf

対話形式で利用したいが、最初に前提条件を毎回手入力するのは面倒である。 以下のような決まり文句を~/llama.cpp/prompt.txtとして用意する。

$ cat ~/llama.cpp/prompt.txt
You (Alice) are a helpful assistant. Please answer a human (User)'s questions.
User: Hello.
Alice:

この決まり文句を最初は以下のように書いていたのだが、なぜか全く反応が返って来なかった。

You (Alice) are a helpful assistant. Please answer a human (User)'s questions.
User: Hello. I am glad to see you.
Alice:

モデルを動かす

llama.cppの配布物に含まれているexamples/chat.shを参考に、 以下のように起動させた。

$ cd ~/llama.cpp
$ llama-cli -m ./models/llama-2-7b-chat.Q4_K_M.gguf -c 512 -b 1024 -n 256 --repeat_penalty 1.0 -t 8 --color -i -r "User:" --in-prefix " " -f prompt.txt
Log start
main: build = 0 (unknown)
main: built with gcc (nb2 20240221) 12.3.0 for x86_64--netbsd
main: seed  = 1718791141
llama_model_loader: loaded meta data with 19 key-value pairs and 291 tensors from ./models/llama-2-7b-chat.Q4_K_M.gguf (version GGUF V2)
llama_model_loader: Dumping metadata keys/values. Note: KV overrides do not apply in this output.
llama_model_loader: - kv   0:                       general.architecture str              = llama
llama_model_loader: - kv   1:                               general.name str              = LLaMA v2
llama_model_loader: - kv   2:                       llama.context_length u32              = 4096
llama_model_loader: - kv   3:                     llama.embedding_length u32              = 4096
llama_model_loader: - kv   4:                          llama.block_count u32              = 32
llama_model_loader: - kv   5:                  llama.feed_forward_length u32              = 11008
llama_model_loader: - kv   6:                 llama.rope.dimension_count u32              = 128
llama_model_loader: - kv   7:                 llama.attention.head_count u32              = 32
llama_model_loader: - kv   8:              llama.attention.head_count_kv u32              = 32
llama_model_loader: - kv   9:     llama.attention.layer_norm_rms_epsilon f32              = 0.000001
llama_model_loader: - kv  10:                          general.file_type u32              = 15
llama_model_loader: - kv  11:                       tokenizer.ggml.model str              = llama
llama_model_loader: - kv  12:                      tokenizer.ggml.tokens arr[str,32000]   = ["<unk>", "<s>", "</s>", "<0x00>", "<...
llama_model_loader: - kv  13:                      tokenizer.ggml.scores arr[f32,32000]   = [0.000000, 0.000000, 0.000000, 0.0000...
llama_model_loader: - kv  14:                  tokenizer.ggml.token_type arr[i32,32000]   = [2, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, ...
llama_model_loader: - kv  15:                tokenizer.ggml.bos_token_id u32              = 1
llama_model_loader: - kv  16:                tokenizer.ggml.eos_token_id u32              = 2
llama_model_loader: - kv  17:            tokenizer.ggml.unknown_token_id u32              = 0
llama_model_loader: - kv  18:               general.quantization_version u32              = 2
llama_model_loader: - type  f32:   65 tensors
llama_model_loader: - type q4_K:  193 tensors
llama_model_loader: - type q6_K:   33 tensors
llm_load_vocab: special tokens cache size = 259
llm_load_vocab: token to piece cache size = 0.1684 MB
llm_load_print_meta: format           = GGUF V2
llm_load_print_meta: arch             = llama
llm_load_print_meta: vocab type       = SPM
llm_load_print_meta: n_vocab          = 32000
llm_load_print_meta: n_merges         = 0
llm_load_print_meta: n_ctx_train      = 4096
llm_load_print_meta: n_embd           = 4096
llm_load_print_meta: n_head           = 32
llm_load_print_meta: n_head_kv        = 32
llm_load_print_meta: n_layer          = 32
llm_load_print_meta: n_rot            = 128
llm_load_print_meta: n_embd_head_k    = 128
llm_load_print_meta: n_embd_head_v    = 128
llm_load_print_meta: n_gqa            = 1
llm_load_print_meta: n_embd_k_gqa     = 4096
llm_load_print_meta: n_embd_v_gqa     = 4096
llm_load_print_meta: f_norm_eps       = 0.0e+00
llm_load_print_meta: f_norm_rms_eps   = 1.0e-06
llm_load_print_meta: f_clamp_kqv      = 0.0e+00
llm_load_print_meta: f_max_alibi_bias = 0.0e+00
llm_load_print_meta: f_logit_scale    = 0.0e+00
llm_load_print_meta: n_ff             = 11008
llm_load_print_meta: n_expert         = 0
llm_load_print_meta: n_expert_used    = 0
llm_load_print_meta: causal attn      = 1
llm_load_print_meta: pooling type     = 0
llm_load_print_meta: rope type        = 0
llm_load_print_meta: rope scaling     = linear
llm_load_print_meta: freq_base_train  = 10000.0
llm_load_print_meta: freq_scale_train = 1
llm_load_print_meta: n_ctx_orig_yarn  = 4096
llm_load_print_meta: rope_finetuned   = unknown
llm_load_print_meta: ssm_d_conv       = 0
llm_load_print_meta: ssm_d_inner      = 0
llm_load_print_meta: ssm_d_state      = 0
llm_load_print_meta: ssm_dt_rank      = 0
llm_load_print_meta: model type       = 7B
llm_load_print_meta: model ftype      = Q4_K - Medium
llm_load_print_meta: model params     = 6.74 B
llm_load_print_meta: model size       = 3.80 GiB (4.84 BPW)
llm_load_print_meta: general.name     = LLaMA v2
llm_load_print_meta: BOS token        = 1 '<s>'
llm_load_print_meta: EOS token        = 2 '</s>'
llm_load_print_meta: UNK token        = 0 '<unk>'
llm_load_print_meta: LF token         = 13 '<0x0A>'
llm_load_tensors: ggml ctx size =    0.15 MiB
llm_load_tensors:        CPU buffer size =  3891.24 MiB
..................................................................................................
llama_new_context_with_model: n_ctx      = 512
llama_new_context_with_model: n_batch    = 512
llama_new_context_with_model: n_ubatch   = 512
llama_new_context_with_model: flash_attn = 0
llama_new_context_with_model: freq_base  = 10000.0
llama_new_context_with_model: freq_scale = 1
llama_kv_cache_init:        CPU KV buffer size =   256.00 MiB
llama_new_context_with_model: KV self size  =  256.00 MiB, K (f16):  128.00 MiB, V (f16):  128.00 MiB
llama_new_context_with_model:        CPU  output buffer size =     0.12 MiB
llama_new_context_with_model:        CPU compute buffer size =    70.50 MiB
llama_new_context_with_model: graph nodes  = 1030
llama_new_context_with_model: graph splits = 514

system_info: n_threads = 8 / 16 | AVX = 1 | AVX_VNNI = 0 | AVX2 = 1 | AVX512 = 0 | AVX512_VBMI = 0 | AVX512_VNNI = 0 | AVX512_BF16 = 0 | FMA = 1 | NEON = 0 | SVE = 0 | ARM_FMA = 0 | F16C = 1 | FP16_VA = 0 | WASM_SIMD = 0 | BLAS = 1 | SSE3 = 1 | SSSE3 = 1 | VSX = 0 | MATMUL_INT8 = 0 | LLAMAFILE = 1 |
main: interactive mode on.
Reverse prompt: 'User:'
Input prefix: ' '
sampling:
        repeat_last_n = 64, repeat_penalty = 1.000, frequency_penalty = 0.000, presence_penalty = 0.000
        top_k = 40, tfs_z = 1.000, top_p = 0.950, min_p = 0.050, typical_p = 1.000, temp = 0.800
        mirostat = 0, mirostat_lr = 0.100, mirostat_ent = 5.000
sampling order:
CFG -> Penalties -> top_k -> tfs_z -> typical_p -> top_p -> min_p -> temperature
generate: n_ctx = 512, n_batch = 1024, n_predict = 256, n_keep = 1


== Running in interactive mode. ==
 - Press Ctrl+C to interject at any time.
 - Press Return to return control to the AI.
 - To return control without starting a new line, end your input with '/'.
 - If you want to submit another line, end your input with '\'.

 You (Alice) are a helpful assistant. Please answer a human (User)'s questions.
User: Hello.
Alice: Hello! How can I assist you today? Is there anything you need help with?

ここで「 Hello! How can I assist you today? Is there anything you need help with?」の部分が、モデルの生成した部分である。 また、本来はここで"User: "と表示されるのを期待しているのだが、なかなか表示されない。 表示されることもある。 良く理由は分かっていない。 ただ、"User: "が表示されなくても、利用はできる。

指示をしてみると、それっぽい返答をしてくれる。

 Tell me the largest city in Asia.
Alice: The largest city in Asia is Tokyo, Japan. It has a population of over
38 million people and is known for its vibrant culture, cutting-edge technology,
and historic landmarks such as the Tokyo Tower and the Meiji Shrine. Would you
like to know anything else?

「Tell me the largest city in Asia.」の部分が私がキーボードから入力した部分である。

かりんとうの製造特許を探す

ALIC (独立行政法人 農畜産業振興機構)のウェブサイトには、いろいろおもしろい記事が掲載されているのだが、 そもそも、私はそれが検索で引っ掛かるような検索キーワードで検索することもないので、 自分で能動的に読みに行かないと、読む機会がなくなってしまう。

砂糖のついての記事を読んでいると、かりんとうについての記事が2つあった。 かりんとうと砂糖日本の味「かりんとう」である。 いずれにも、過去にかりんとうの製造方法についての特許があったことが記載されている。

かりんとうと砂糖には、以下のように記載されている。

昭和41年  農林省指令41A第2581号を以って公認組合として認可され、全国油菓工業組合として新発足する。
 某企業が、かりん糖の特許を出願したのを機に組合にその「かりん糖の製造特許権」が譲渡され、この権利を公平適切に運用することで各企業が組合に加入した。

日本の味「かりんとう」には、以下のように記載されている。

 当組合の組合員しか知らない、かりんとうのビックリする話があります。

 江戸の昔からある「かりんとう」に「製造特許」が存在していたということです。いきさつはいろいろあったと思いますが、戦後景気が回復し、いろいろなお菓子が作られるようになりました。当時下請けをしていたあるかりんとう業者が、親会社からの厳しい要求の対応として「穀物を練り発酵させて棒状に切り、油で揚げた物に砂糖をかけた菓子」の製造特許を申請したところ、昭和41年にその特許が認められたのです。「これは大変」と各メーカーが騒いだのですが、結局その特許権を組合に譲渡することで落ち着き、昭和55年に特許権が消滅するまで当組合が保持し、かりんとうメーカーは特許使用料を当組合に支払っていました。

これらを解釈すると、昭和41年(1966年)に特許が成立し、昭和55年(1980年)まで特許は有効であったということであろう。 日本の特許は出願から20年間保護されるのだったと思うので、出願は昭和35年(1960年)にされているはずである。 あるいは、20年間を満了せずに、年金を払わずに消滅したのかもしれない。

特許情報プラットフォームで全文検索してみたが、どうやら1970年くらいに出願された以降のものしか 全文検索はできないように見える。 また、出願日1960年に絞り込み、FIをA23に絞り込んで見て行っても、それらしい特許を見付けることはできなかった。

そこで、最近のかりんとうの製造方法についての特許から引用されているのではないかと考え探すと、おそらくこれではないかというものを見付けることができた。

それは、特許3873479「かりんとうの製造方法」において、 引用調査データとして引用されている「特公昭40-002849 (かりんとうの製造方法)」である。これは、特許0470216なはずなのだが、この特許の内容は特許情報プラットフォームには登録されていないようである。

しかし、この特許は昭和38年2月11日に出願されており、昭和41年に特許が成立していてもおかしくはないが、昭和55年に期間満了となったとは思えない。 経過情報も参照できないので、いつ特許0470216が成立したのか、失効したかも分からない。 出願人は荒井公平という人だが、どの企業がこの特許の背景にいるのかも分からなかった。この名前の方は、和菓子では有名な方のようだが、同一人物かも分からない。

"LGPL and Java"を読んだ

JavaというかJVMを使わないといけないような気がしていて、Javaの場合にLGPLがどう働くのかが気になっていた。 LGPL and Java を読んでみた。 今まで気にしたことはなかったが、www.gnu.orgの文書は、基本的にはCreative Commo...