計測台に置いたノートPC、計測機器、デスクトップPCで表したPoC実験。

Edge0連載 5: M2 Air 16GBでの実測と社内PoCへの拡張条件

16GBのM2 MacBook Airで、Microsoft Learn検索、Edge0ストリーミング、文単位の韓国語翻訳を接続したエージェントを実行しました。2026年9月13日に確認したサンプルGistには、コード全体とともにTTFTが53.47秒だった実行結果を公開しています。 最終回では、計測に使った質問、検索と最初の応答までの時間、生成回答の根拠、出力速度の解釈、今後の最適化、社内PoCへ拡張する条件を扱います。第4回で説明したクライアント側の計測を基準に結果を読みます。 実行ログと計測値から説明します。各段階の時間を比較し、現在の結果から判断できる範囲と、追加実験が必要な範囲を分けて扱います。 数値を比較する際は、次の基準を適用します。 文書は2026年9月13日に確認しました。以下の数値は、特定の質問と検索結果を使用した一度の実行記録です。当時のすべてのバージョン、キャッシュ状態、反復計測の結果は、この記録だけでは確認できません。tok/sと表示した値は、コンテンツを含むSSEイベント数から計算しています。 Native AOTの質問を使った単一実行 実験にはM2 MacBook Air 16GBとEdge0-35B-A3B-previewを使用しました。PythonホストがMicrosoft Learnを検索し、Apple Translationで入出力を翻訳する構成は、Gistの実行手順と同じです。 質問は次のように入力しました。 NativeAOT에서 Reflection.Emit을 사용할 수 있는지도 설명해주세요. モデルの一般知識を評価するよりも、検索した公式文書を読み、実行時コード生成の対応有無を判定できるかを確認しました。この一度の結果を、機器の平均性能や別の質問の回答品質へ一般化してはいません。 検索完了から最初の応答までの待ち時間 サンプルコードの状態メッセージは、入力処理の開始を基準に経過時間を表示します。TTFTは、Edge0リクエストの開始時に記録する別の時刻を基準に計算します。 質問変換と検索にかかった約2.6秒 韓国語の案内を使った実験ログでは、次の順序で検索を完了しました。現在のGistは同じ種類の案内を英語で表示します。 [ 0.0s] 한국어 질문 정규화 [ 1.3s] 영어 검색 질의 생성 완료 [ 1.3s] Microsoft Learn 검색 [ 2.6s] 관련 문서 3개 검색 완료 근거 자료 [1] Native AOT deployment [2] Introduction to AOT warnings [3] ASP.NET Core support for Native AOT 約2.6秒には、韓国語の質問の正規化、英語クエリの生成、Microsoft Learn検索が含まれます。この実行では、その区間は後続の最初の応答までの待ち時間より短くなりました。 ...

2026年9月17日 · 2 分 ·  rkttu
時間を測る装置とノートPCの間のレール上で、最初の空白区間に続いて並ぶ青いガラスのパネル。

Edge0連載 4: ストリーミング応答のTTFTと出力速度の計測

2026年9月13日時点で、連載のPythonサンプルはEdge0のSSE応答を受信しながら、最初の応答までの待ち時間と出力速度を記録します。今回は第3回で作ったグラウンディング用プロンプトを実際の生成リクエストへ接続します。 この記事では、計測時点、待機状態の表示、ワーカースレッドでの受信、文単位の韓国語翻訳、計測値の解釈を扱います。16GBのM2 MacBook Airでの実験では最初の応答まで数十秒かかったため、その前後の時間を分けて記録しました。 計測値の定義から説明します。サーバー応答の受信と画面出力を分離し、生成文を翻訳して最後に指標を表示する順に進めます。プログラム全体にはGistのmicrosoft_expert_agent.pyを使用します。 以下の計測は、次の範囲で解釈します。 公開資料は2026年9月13日に確認しました。Edge0-35B-A3B-previewと公開ストリーミングインターフェースを前提とします。サンプルはクライアントが観測した時間とコンテンツイベント数を記録し、サーバー内部のプリフィル、デコード、待機時間を個別には計測しません。 最初のコンテンツと受信終了を基準にした計測値 GistのStreamStatsは、リクエストを処理するワーカースレッドを起動する直前に基準時刻を保存します。その後、空でない最初のコンテンツを受信した時刻と、ストリームの受信を終えた時刻を記録します。 TTFT:リクエストの基準時刻から最初のコンテンツを受信するまでの時間を測ります。クライアントが観測した最初の出力までの待ち時間を表します。 総生成時間:リクエストの基準時刻からストリームの受信が終わるまでの時間を測ります。検索時間は含まず、韓国語翻訳がすべて完了する時点までは測りません。 生成量:コンテンツを含むSSEイベント数を数えます。現在の転送動作を前提に、この値をトークン数の推定値として使います。 最初の応答後の時間:最初のコンテンツを受信してからストリームの受信が終わるまでの時間を測ります。ネットワーク受信や終了処理にかかる時間も含みます。 出力速度:生成量を最初の応答後の時間で割ります。コンテンツイベント単位で処理率を計算します。 時刻と生成量を保存するオブジェクト 既存サンプルのフィールド名と計算式を保持した計測オブジェクトを示します。 from dataclasses import dataclass @dataclass class StreamStats: request_started: float = 0.0 first_token_at: float | None = None done_at: float | None = None completion_tokens: int = 0 @property def ttft(self) -> float | None: if self.first_token_at is None: return None return self.first_token_at - self.request_started @property def total_generation_time(self) -> float | None: if self.done_at is None: return None return self.done_at - self.request_started @property def decode_time(self) -> float | None: if self.first_token_at is None or self.done_at is None: return None return self.done_at - self.first_token_at @property def output_tokens_per_second(self) -> float | None: duration = self.decode_time if not duration or duration <= 0: return None return self.completion_tokens / duration TTFTには、スレッド起動、HTTP処理、サーバーのキュー待ち、トークン化、プリフィル、最初の生成ステップの時間が含まれる場合があります。decode_timeという名前のフィールドも、サーバー内部の純粋なデコード時間だけを意味しません。 ...

2026年9月16日 · 3 分 ·  rkttu
文書の強調箇所を拡大する虫眼鏡と、選択した3枚の参照カードを入れたガラスの箱。

Edge0連載 3: Microsoft Learn検索を組み込むローカルRAGエージェント

2026年9月13日時点で、サンプルGistはEdge0サーバー、Microsoft Learn CLI、Apple TranslationをPythonで接続するコードを提供しています。第2回で準備した環境を基に、今回は検索した資料をモデルの入力に変える部分を説明します。 この記事では、ホストとモデルの役割分担、質問の正規化と翻訳、検索結果の選択、グラウンディング用プロンプト、会話コンテキストの管理を扱います。ホストが検索の順序を決め、モデルは渡された資料を読んで回答を構成します。 データ構造と入力処理から説明します。検索した箇所に出典番号を付け、現在の質問と一緒に渡した後、続く質問に必要な文脈を構成します。ストリーミング要求と性能計測は第4回で扱います。 本文のコードと公開バージョンは、次の範囲で扱います。 公開資料は2026年9月13日に確認しました。本文ではRAGの流れを説明するためにコードを抜粋し、実行ファイル全体に含まれる一部の補助処理を省略しています。Edge0-35B-A3B-previewの動作や外部ツールの応答形式は、今後変わる可能性があります。 検索とコンテキスト構成を担うPythonホスト Pythonコード全体では、ホストが入力を正規化して翻訳し、Microsoft Learnを検索します。検索結果の重複URLを除き、資料の長さを制限し、直近の会話をリクエストに含めます。 モデルの役割は、質問と文書の関係を把握し、回答に使う根拠を選び、英語で回答を生成することに絞ります。資料から事実を確認できない場合は、根拠が不足していると回答するようプロンプトに指定します。 検索結果はタイトル、URL、本文を持つSourceオブジェクトで管理します。入力の量を制限する定数も一緒に定義します。 from dataclasses import dataclass @dataclass class Source: title: str url: str content: str MAX_SOURCES = 3 MAX_SOURCE_CHARS = 1800 MAX_SOURCE_CHARSは各検索箇所の文字数を制限します。出典タイトル、URL、システムプロンプト、会話履歴はこの上限の外で追加するため、リクエスト全体のサイズは別途計算できます。 間接疑問文を直接疑問文に変えるルール 韓国語の質問の正規化は、Gistのnormalize_korean_question()が処理します。生成の有無を尋ねた質問が翻訳時に生成方法を尋ねる依頼へ変わる例を減らすため、決められた文型を変換します。 次の関数は四つのパターンに一致する文を、直接疑問文と後続の依頼に分けます。 import re def make_followup(action: str) -> str: if action == "알려주세요": return "그 여부도 알려주세요." if action == "확인해주세요": return "그 여부도 확인해주세요." return "그 여부도 설명해주세요." def normalize_korean_question(text: str) -> str: suffix = ( r"\s*(?:함께\s*)?" r"(설명해주세요|알려주세요|확인해주세요)" r"\.?$" ) patterns = [ ( rf"^(.*)할 수 있는지도{suffix}", lambda m: f"{m.group(1)}할 수 있습니까? " f"{make_followup(m.group(2))}", ), ( rf"^(.*)되는지도{suffix}", lambda m: f"{m.group(1)}됩니까? " f"{make_followup(m.group(2))}", ), ( rf"^(.*)하는지도{suffix}", lambda m: f"{m.group(1)}합니까? " f"{make_followup(m.group(2))}", ), ( rf"^(.*)필요한지도{suffix}", lambda m: f"{m.group(1)}필요합니까? " f"{make_followup(m.group(2))}", ), ] for pattern, replacement in patterns: match = re.match(pattern, text) if match: return replacement(match) return text パターンに一致しなければ、入力をそのまま返します。文型を追加する際には、原文、変換結果、英語訳を比較すると、質問の意味を維持できているか確認できます。 ...

2026年9月15日 · 3 分 ·  rkttu
ノートPCの前で接続した演算装置、文書カード、半透明の吹き出し。

Edge0連載 2: Microsoft LearnとApple Translationの実行環境

2026年9月13日時点で、この連載のサンプルはEdge0-35B、Microsoft Learn CLI、macOSのTranslationフレームワークを使用します。第1回で決めた役割分担に沿って、推論サーバーとPythonエージェントのホストを別々のターミナルで実行します。 この記事ではEdge0とモデルの導入、ストリーミングサーバーの起動、公式文書の検索、韓国語と英語の翻訳、質問の正規化を扱います。ファイル全体はサンプルGistのREADME.md、apple_translate.swift、microsoft_expert_agent.pyにあります。 実行条件とインストール手順から説明します。最初のターミナルでサーバーを起動した後、検索ツールと翻訳CLIを準備し、二つ目のターミナルでエージェントを実行できる状態にします。 以下の手順は、次の公開バージョンとAPI条件を前提にしています。 文書は2026年9月13日に確認しました。Edge0-35B-A3B-previewの構成は今後変わる可能性があります。Swiftの例で使用するTranslationSession(installedSource:target:preferredStrategy:)は、macOS 26.4以降と、このAPIを含むSDKを前提とします。 Edge0と35Bモデルの導入条件 実験にはApple Silicon Mac、Python 3.12、Node.js 22以降、Xcode Command Line Toolsを使用します。約23GBのモデルファイルを保存する空き容量と、韓国語および英語の翻訳リソースも用意します。対応環境とモデルファイルの構成は公式READMEに記載されています。 リポジトリとPython仮想環境 作業ディレクトリでリポジトリを取得し、仮想環境を有効にしてサンプルの依存関係をインストールします。 git clone https://github.com/Edge0-AI/Edge0.git cd Edge0 python3.12 -m venv .venv source .venv/bin/activate pip install -e '.[dev,fetch]' pip install flask requests 以後のコマンドはEdge0リポジトリのルートを作業ディレクトリにします。flaskはストリーミング転送、requestsはPythonホストのHTTPリクエストに使用します。 モデルのダウンロードとパスの指定 公式スクリプトで35Bモデルを取得し、現在のシェルにモデルパスを設定します。 python scripts/fetch_models.py \ --tier edge0-35b \ --target-dir models export EDGE0_35B_MODEL="$PWD/models/edge0-35b" models/edge0-35b/には、設定、モデルの重み、トークナイザー、LoRAとプリルーターのアダプターが含まれます。アダプターを含むディレクトリ全体をモデルパスとして指定します。 最初のターミナルで動かすストリーミングサーバー Edge0の35Bモデル文書は、Flask転送層によるSSEストリーミングと、状態確認用の/healthzを説明しています。このサンプルでは接続先を127.0.0.1:8083に設定します。 仮想環境の再有効化とサーバー起動 新しいターミナルでは、作業パス、仮想環境、モデルの環境変数を再設定します。/path/to/Edge0は、リポジトリを取得した実際のパスに置き換えます。 cd /path/to/Edge0 source .venv/bin/activate export EDGE0_35B_MODEL="$PWD/models/edge0-35b" edge0 serve edge0-35b \ --host 127.0.0.1 \ --port 8083 \ --flask サーバーの実行中は最初のターミナルを開いたままにします。別のターミナルで有効にした仮想環境は、新しいシェルに自動では適用されません。 ...

2026年9月14日 · 2 分 ·  rkttu
銀色のノートPCの上に浮かぶガラスのブロックと積み重ねたストレージで表したローカルモデルの推論。

Edge0連載 1: 16GB Macで動かす35BローカルLLMと根拠に基づくエージェント

2026年9月13日時点で、Edge0はApple Silicon向けのMLXバックエンドとEdge0-35B-A3B-previewモデルを公開しています。私は16GBのM2 MacBook Airでこのモデルを実行し、Microsoft Learnの資料を根拠に回答する技術専門エージェントを構成しました。 この連載では、35Bクラスのモデルを動かす条件、検索資料による回答の変化、韓国語の入出力、ストリーミング性能の計測、社内PoCへ拡張する条件を扱います。実行コード全体はEdge0 Microsoft Technology Expert AgentのGistにまとめています。 第1回ではモデルを実行した経験から説明します。外部の根拠を与えた実験と入力資料を短くした結果を比較し、後続の記事で実装するエージェントの構造を紹介します。 公開状況と計測結果には、次の範囲を適用します。 公開文書は2026年9月13日に確認しました。モデルはプレビュー段階にあり、構成や性能は今後変わる可能性があります。実行時間と回答例は私が行った個別の実験記録であり、すべての機器や質問に共通する性能を示すものではありません。 必要な重みをSSDから読み込む35Bモデル Edge0のメモリ利用方式から確認します。プロジェクトの説明によると、Edge0は疎なMoEモデルのエキスパート重みをSSDに置き、推論に必要な部分を読み込みます。このため、起動時にモデル全体をRAMへ読み込む構成とはメモリの利用状況が異なります。 公開モデルの仕様と公式の計測値、私の実験環境を項目ごとに分けて示します。 公開モデル:Edge0-35B-A3B-previewは35BクラスのMoE構造に4ビット量子化を適用しています。 モデルファイルのサイズ:SSDに保存するチェックポイントは約23GBを占めます。 公式のメモリ計測値:短いコンテキストで、MLXアロケーターの最大アクティブメモリが約2.9GiBを記録しました。 個人の実験機器:この連載ではM2 MacBook Air 16GBを使用しました。 最初の生成実験:特定の入力と実行条件で、128トークンの生成に約43.8秒かかりました。 公式のメモリ値はシステム全体の使用量を表していません。OS、トークナイザー、キャッシュ、コンテキスト長による追加の使用量も考慮できます。重みの読み込み経路はアーキテクチャ文書が説明しています。 私の機器でもモデルは文章を生成しました。16GBのノートPCで実行できることを確認したうえで、応答速度と回答の正確さは別々に評価しました。 外部の根拠を中心にした回答生成 質問だけを与えるzero-shotの実験では、C# Native AOTとRustのコンパイルモデルを誤って説明する回答がありました。英語の質問でも同様の誤りが繰り返されました。十分な数の質問を用いた品質評価ではないため、この経験だけでモデル全体の性能は判断していません。 そこで、事実知識をモデル自身に任せる範囲を狭めました。自分で回答を評価できる.NET Native AOTとJITの質問を使い、Microsoft LearnのNative AOT文書を一緒に渡しました。 その後のエージェントでは、役割を次のように分けました。図内の表記は韓国語原稿のまま保持しています。 Edge0 질문과 문서의 내용 파악 관련 근거 선택 근거에 따른 답변 생성 외부 시스템과 Python 호스트 공식 문서 검색 입력 자료 구성 대화 상태 관리 한국어 입출력 처리 実験では、モデルが渡された文書を読み、質問に合う回答を構成できるかに焦点を当てました。 ...

2026年9月13日 · 1 分 ·  rkttu