[go: up one dir, main page]
More Web Proxy on the site http://driver.im/

2024年の技術動向まとめ

年末だし、今年の技術まとめを主観的に書いておきますね。

動画生成AIはじまる

2月にOpenAIのSoraが発表されて、動画生成AIが盛り上がりはじめました。
12月に一般公開されましたが、それまでにも複数の動画AIモデルが発表されて、動画生成AIの実用化がはじまった年になったように思います。

とはいえ、なんだか微妙だなーという感じ。

デモは、ベストofベストだったなーと。
生成できそうな動画を生成するのが大事そう。

エージェントによる推論スケーリング

OpenAIのo1が9月に発表され、推論に計算力を使うことでもスケーリングすることが示されました。
思考方針を管理するモデルが、内部で実際に思考を行うモデルに推論を行わせて、その結果をまとめて表示するような仕組みです。そうやって、推論時にコストをかけることでも性能が出せるようになっています。
論理的な問題に強さがある一方で、日常的な用途では5月に発表された4oが必要十分な性能を出しており、なかなか使い所が難しいなという気がしています。

小規模言語モデル

昨年12月のMicrosoftのPhi-2や今年2月のGoogleのGemmaから注目されはじめた小規模な言語モデルが、性能もあがって実用的になってきました。
今月発表されたSarashina2.1-1Bでは、1Bという小さなモデルであるにもかかわらず、完全なJavaコードの生成ができています。

https://huggingface.co/sbintuitions/sarashina2.1-1b
もちろん、ちゃんとコードを書かせるという用途に使えるほどではないけど、モデルサイズを考えるとすごい。もう少しモデルサイズを大きくすれば十分な性能が出そうでもある。

マイクロソフトは小さな言語モデルをSLMと呼んでいますが、同じ技術をサイズで用語をわけるというのは筋が悪いなと思っています。AI Insideは47BのモデルをSLMと呼んだりしてますが、さすがに高性能なゲーム用GPUでも動かせないモデルはSLMという言葉を使う意図から外れてるんではと思ったり。

WebAssemblyの活性化

8月にSafariでもWebAssembly(WASM)にGCが組み込まれたプレビューが出たことで、WASMの利用が本格化してきたように思います。
https://www.publickey1.jp/blog/24/safariwasmgcsafari_technology_preview_202wasmgc.html

LLVMを使う言語だけではなく、JavaScript/TypeScriptやPyhotn、Flutter/DartでもWASMに対応してきています。
JavaでもCheerpJ 3.0がWASM対応で実装されなおしています。また、このCheerpJを転用してx86コードが動くようにもなっていますね。

ARM版Windowsはじまった?

QualcommのSnapdragon X Elite/Plusを搭載したWindowsマシンが6月に発表されリリースされました。性能も遜色ないものになっているようです。 また、x86エミュレータも割と本気を出してきたようで、WindowsでもARMが選択肢になってきました。
同時に、Copilot+PCやAI PCといって、最低メモリ容量を16GBとしたことで、今後は16GBのメモリを載せたモデルが標準になってくるというのも、うれしいかもしれません。

雑感

LLMの単体モデルの高性能化は4oくらいで伸び悩み始めたような感じがあります。学習データの枯渇や計算リソースの制限のような学習側の問題だけではなく、実用として4o程度の性能があれば十分になってきて、これ以上のモデルを開発する経済合理性も下がってきているような。
そこでエージェントを使うようなo1が出たり、より小さなモデルで性能を出すという方向にシフトしている感じがします。
また、チャットUIで直接LLMと対話する場合の性能は十分になってきたというか、これ以上を求める場合のギャップを乗り越えるのが難しくなってきていて、今後はたとえばGoogleのAstraやOpenAIのAdvanced Voice Modeように状況を見ながらサポートをしてくれるようなものなど、アプリケーションとの統合が大切になってくるように思います。
AI領域以外では、WebAssemblyが領域を広めるということの他に、そろそろRISC-VがWebサーバーなどの分野でも話が聞こえてくるかもな、というところかな。

「Java Webフレームワークの現状」でJJUG CCC 2024 Fallで登壇してきました

JJUG CCC 2024 Fallで「Java Wevフレームワークの現状」というタイトルで登壇してきました。
漠然としていたところが整理されてよかった、という感想が多かったので、いい話だったっぽい。

「Java 23新機能まとめ」を書きました

Qiitaのほうに「Java 23新機能まとめ」を書きました。

WebAssemblyにコンパイルしたRustコードにJavaインタフェースをマッピングする

Chicoryを使ってRustをコンパイルしたwasmをJavaから呼び出してみました。
JVMでWebAssemblyにコンパイルしたRustのコードを動かす - きしだのHatena

ただ、結構呼び出しがめんどいので、Javaインタフェースを定義したらなんかメソッド呼び出しで使える、というよく見かけるやつを作ってみます。

Rustのコードはこう。

#[no_mangle]
pub fn add(left: i32, right: i32) -> i32 {
    left + right
}

#[no_mangle]
pub fn sub(left: i32, right: i32) -> i32 {
    left - right
}

#[no_mangle]
pub fn mul(left: i32, right: i32) -> i64 {
    (left as i64) * (right as i64)
}

こんなJavaインタフェースで呼び出せるようにしたい。

interface RustFuncs {
    int add(int left, int right);
    int sub(int left, int right);
    long mul(int left, int right);
}

ということで、こんな感じでProxyを作る。

static <T> T bind(String name, Class<T> type) {
    var wasm = CallWasm.class.getClassLoader().getResourceAsStream(name);
    var module = Module.builder(wasm).build();
    var instance = module.instantiate();

    T obj = (T) Proxy.newProxyInstance(type.getClassLoader(), new Class<?>[]{type}, 
            (p, m, a) -> methodHandler(instance, type, p, m, a));
    return obj;
}

static Object methodHandler(Instance ins, Class type,
        Object proxy, Method method, Object[] args) throws Throwable {
    var m = ins.export(method.getName()); // todo:use annotation name
    List<Value> values = new ArrayList<>();
    for (int i = 0; i < args.length; ++i) {
        values.add(switch (args[i]) {
            case Integer n -> Value.i32(n);
            case Long l -> Value.i64(l);
            default ->throw new RuntimeException("unknown type " + method.getParameterTypes()[i]);
        });
    }
    var result = m.apply(values.toArray(Value[]::new))[0];
    var rt = method.getReturnType();
    if(rt == long.class || rt == Long.class) {
        return result.asLong();
    } else if (rt == int.class || rt == int.class) {
        return result.asInt();
    } else {
        throw new RuntimeException("unknown ret type " + rt);
    }
}

こうやって呼び出せるようになりました!やったね!

public static void main(String[] args) throws IOException {
    var rf = bind("hello_wasm.wasm", RustFuncs.class);
    System.out.println(rf.add(12, 34));
    System.out.println(rf.sub(34, 12));
    System.out.println(rf.mul(100_000_000, 100_000_000));
}

文字列とかはwasmでは定義されてなくて結構めんどいので、そのあたりはもう少し考えてみます。
使い物になりそうだったらasmかJavassistバイトコード生成を。

ITが面白い時代はすでに終わっているし変化も遅くなった

ITはもう面白くなくなってますね。
技術が面白いときには、いろいろ新しいものが出て性能あがったりできることが増えたりします。調べたらどんどん新しいものが出てくるし、新しいものもたくさん作るし、面白い。ですが、IT技術は一通り出そろって、成熟期に入っています。そうすると新しい技術に出会うことも新しいものを作ることも減っていきます。その結果、いままでの変化のあった状況を知っていれば、つまらんってなりますね。

※2024/8/24 追記 言いたいことをまとめると、IT素振りのネタ探しに苦労するようになったよねってことです。

結局のところITというのは新しいハードをどう動かして社会に実装していくかというものなので、新しいハードが出ないとどうしようもないのです。けれどもだいたい飽和してしまった。

雑にいえば、これまで1980年くらいにBASIC搭載8bitパソコンが普及するとBASICプログラミングが流行り、1990年くらいにパソコンが32bit化するとGUIシステムが使い物になるようになってWindowsやそのうえで動くソフトの開発が流行り、2000年くらいから常時接続インターネットが広まり始めたりiモードなどモバイルインターネットが可能になってネットワークサービスの開発が流行りブログや2chのような文字ベースのサービスが広まって、2005年くらいからマルチコアのプロセッサが広まると仮想化やらクラウドの流れが本格化してmixiのようなSNSが大規模化して、2010年くらいにスマホが広まって4Gでモバイル通信も速くなって動画サービスが当たり前になり、2017年のTikTokくらいでゴール、みたいな感じですね。

その流れから、使われる技術も対応して進化しつつ、プログラミング言語も2014年のSwift以降は広く使われるようなものは出てきていないし、実行基盤も同じ年に出てきたKubernetesで、だいたいの技術は出そろったという感じになっています。

ライブラリやツールも、欲しいものはだいたいすでにあるという状況。オープンソースにコミットしようにもすでに巨大になりすぎてさわれない。

さすがにメシの種がなくなったということで、VRとかブロックチェーンとか5Gとかに目をつけてWeb3として注目されたものの、そこまで流行らなかったですね。

サービス開発の裏で、いつの間にか超並列プロセッサになっていたGPUを使って科学計算しようぜーというのが2007年のCUDAで流行りだして、2011年にディープラーニングがいわれるようになって、見えないところで写真をきれいにしてくれたりラーメン次郎を識別してくれたりというのが発展しつつ、2022年にさっそうと現れたChatGPTによってAIバブルが発生し、つい先日はじけました。

ChatGPTは期待され初速こそ2ヵ月で1億ユーザーを獲得したと話題になりましたが、教育か開発で使われるサービスという感じに落ち着いて、日常生活を変えるかというとそこまで変わらない。
それを使って勉強なり開発なりした人が「新しいサービス」を作らないと世界が変わらない、GitHubに近い位置づけに思います。

もちろん、開発のやりかたとかへの影響は大きいとは思うのだけど、結局「じゃあそれでなにを作るの?」というところが面白くならなければ、「作業のやりかたの話ばかりになってつまらん」というのは変わらない気がする。

ちなみにAIまわりのオープンソースはちょっとさわるとすぐ治せるバグが見つかるし便利機能も実装しやすいのでコミットしやすく最後の楽園っぽさはありますが、それゆえ参加者が多すぎてすぐ食い尽くされそう。

あと、ITでお金を稼ぐには広告一択、にもなってますね。つまり、IT自体ではお金を稼ぐ能力が弱くて、物理サービスの売上を広告で助け、そこで稼がれたお金をもらって成り立つ業界です。

その結果で、面白いことといえば既存産業をITで強くするというDXのようなものが流行り、新しいサービスというのも車がやってきたり料理がやってきたりスキマ時間に働けたり、物理サービスをより最適化するような、どちらかというとITは裏方になったものが多くなってきてますね。

なので、新しいものが出て楽しいというのはもう終わって、IT自体を楽しまないといけない時代、もしくはビジネスを楽しまないといけない時代になっていると思います。

※追記 何人かやりとりして思ったのだけど、ITがようやく道具として使い物になってきたということなのかもな。

JTCは英語の「正しい」語順としてもJTCじゃないんだろうか

JTC、つまりJapanese Traditional Companiesのことですが、英文法チェッカーが「Traditional Japanese Companiesでは?」みたいな指摘をしてきたり、TJCのほうが正しいという話がありますね。

英語の文章でどのような語順で出てくることが多いか数えてTJCのほうがいいのではとしているブログもありました。

けれども、ここでJTCというのは、次の日経記事にあるよう「上意下達の企業文化や硬直的な組織運営を皮肉る際に使われます」という言葉です。
JTC(Japanese Traditional Company)とは? 古い企業体質、変革を模索 - 日本経済新聞

英語でTraditional Japanese Companiesが正しいというには、それが古い企業体質を皮肉る文脈で使われている必要があります。けれどもそんな文脈はほとんどないんじゃないかと。

JTCって、西暦578年創業の金剛組とか西暦1707年創業の赤福とかの話をしたいわけじゃないです。金剛組赤福を言いたいのであれば、Traditional Japanese Companiesでいいと思います。

JTCは「伝統的な日本企業」ではなく「日本のよくある古い企業」を指しているので、Japanese Traditional Companyでいいんじゃないかと思います。少なくとも、「英語でよくつかわれるのはTraditional Japanese CompaniesだからTJCが正しい」というのは根拠にならないんではないかと。

JVMでWebAssemblyにコンパイルしたRustのコードを動かす

Chicoryを使うとJVM上でWebAssemblyを動かせるということで、RustからWebAssemblyにコンパイルしたコードを動かしてみます。

このときはRustをLLVMビットコードにしてGraalVMで動かしていましたね。
GraalVMでRust動かしたりレイトレをネイティブコンパイルしたり - きしだのHatena

Rustからwasmを作成

まずはRustのプロジェクトを作成。

>cargo new --lib hello-wasm
    Creating library `hello-wasm` package

lib.rsというファイルが作成されてadd関数が定義されているので、no_mangleをつけてu64をi32にします。

#[no_mangle]
pub fn add(left: i32, right: i32) -> i32 {
    left + right
}

そしたらビルド

hello-wasm>cargo build --target=wasm32-unknown-unknown --release
   Compiling hello-wasm v0.1.0 (C:\Users\naoki\Desktop\hello-wasm)
    Finished `release` profile [optimized] target(s) in 0.44s

ブラウザで試す

とりあえずブラウザで動かしてみます。こんなJS入りHTMLを書く。

<html>
<head>
 <title>Hello wasm</title>
 <script>
   const wasm = "./target/wasm32-unknown-unknown/release/hello_wasm.wasm"
   fetch(wasm)
    .then(res => res.arrayBuffer())
    .then(b => WebAssembly.instantiate(b, {}))
    .then(res => {
      alert(res.instance.exports.add(2, 3))
    })
  </script>
</head>
</html>

さて、fetchでwasmを読み込んでいるけど、これはファイルシステム経由での読み込みができないので、Webサーバーが必要です。

ここでJava 18で導入されたjwebserver。 https://openjdk.org/jeps/408

ただ、Windowsで起動すると文字化けるです。

hello-wasm>jwebserver
繝・ヵ繧ゥ繝ォ繝医〒繝ォ繝シ繝励ヰ繝・け縺ォ繝舌う繝ウ繝峨@縺セ縺吶ゅ☆縺ケ縺ヲ縺ョ繧、繝ウ繧ソ繝輔ぉ繝シ繧ケ縺ァ"-b 0.0.0.0"縺セ縺溘・"-b ::"繧剃スソ逕ィ縺励∪縺吶・
C:\Users\naoki\Desktop\hello-wasm縺翫h縺ウ繧オ繝悶ョ繧」繝ャ繧ッ繝医Μ繧・27.0.0.1繝昴・繝・000縺ァ菴ソ逕ィ縺励∪縺・URL http://127.0.0.1:8000/

別にコンソールなので文字化けさせておけばいいのだけど、気になるのでchcpコマンドでUTF-8にしておきましょう。

hello-wasm>chcp 65001

気を取り直してjwebserverの起動。

hello-wasm>jwebserver
デフォルトでループバックにバインドします。すべてのインタフェースで"-b 0.0.0.0"または"-b ::"を使用します。
C:\Users\naoki\Desktop\hello-wasmおよびサブディレクトリを127.0.0.1ポート8000で使用します
URL http://127.0.0.1:8000/

http://localhost:8000/hello.htmlにアクセスすると、なんかWebAssemblyが動いてるっぽい。

Chicoryの導入

では、JVMでWebAssemblyを動かすChicoryを導入します。
https://github.com/dylibso/chicory

readmeに従ってdependencyを追加します。

<dependency>
  <groupId>com.dylibso.chicory</groupId>
  <artifactId>runtime</artifactId>
  <version>0.0.12</version>
</dependency>

Javaコードで動かす

では、試しに動かしてみましょう。targetの下の方にhello_wasm.wasmができているので、src/main/resourcesにコピーしておきます。

そして次のコードを。ちなみに、現状のChicoryのreadmeに書いてあるParser.parseを使ったサンプルは、まだ配布バイナリに反映されていません。古い書き方で書く必要があります。

import com.dylibso.chicory.wasm.types.Value;
import com.dylibso.chicory.runtime.Module;
import java.io.IOException;

public class CallWasm {
    public static void main(String[] args) throws IOException {
        var wasm = CallWasm.class.getClassLoader().getResourceAsStream("hello_wasm.wasm");
        var module = Module.builder(wasm).build();
        var instance = module.instantiate();
        var add = instance.export("add");
        
        var result = add.apply(Value.i32(3), Value.i32(2));
        System.out.println(result[0].asInt());
    }
}

実行すると5が表示されて、なにか動いてそう。

まとめ

この記事ではSQLiteをwasmにコンパイルして動かすということもやってます。Cで書かれたコードをJavaで動かしやすくなりそうで、なかなかよさそうですね。
https://www.infoq.com/articles/sqlite-java-integration-webassembly/

ただ、パフォーマンスが必要ならおとなしくネイティブバイナリ使いましょうということになると思うので、テスト用とかですかね。