* 設計概要
完全ローカル · 猫キャラクター家電AIエージェント
6–9
tok/s
~10s
レイテンシ(ツール無)
~30s
レイテンシ(ツール有)
3.4GB
llama-server RAM
6
ツール数
7
SwitchBot devices
768d
埋込ベクトル次元
30–50
自律呟き / 日
システム概要
graph LR
subgraph HW["Raspberry Pi 5 + Whisplay HAT"]
Mic["マイク · WM8960"]
Btn["ボタン · GPIO"]
end
subgraph Core["neko.py - メインループ"]
VAD["silero-vad 16kHz"]
SM["State Machine 5 states"]
Auto["Autonomous Loop 15-90min"]
end
subgraph ADK["agent.py - ADK + LiteLLM"]
Agent["LlmAgent function calling"]
Gemma["Gemma 4 E2B Q4_K_M port8080"]
end
subgraph ToolBox["tools.py - 6 Tools"]
T1["observe"] T2["control_device"] T3["remember"]
T4["activity"] T5["broadcast"] T6["web_search"]
end
subgraph IO["I/O"]
SPK["スピーカー"] LCD["LCD 240x280"]
BSKY["Bluesky"] SB["SwitchBot"] CAM["Camera"]
end
Mic --> VAD --> SM
Btn --> SM
SM --> Agent
Auto --> Agent
Agent <--> Gemma
Agent --> T1 & T2 & T3 & T4 & T5 & T6
T1 --> CAM & SB
T2 --> SB
T5 --> SPK & BSKY
SM --> LCD
技術スタック
採用技術と不採用の経緯
| 領域 | 採用 | 理由 |
|---|---|---|
| 推論エンジン | llama.cpp --jinja --ctx-size 12288 | Gemma 4 音声入力対応、ローカル完結 |
| LLM | Gemma 4 E2B Q4_K_M + mmproj-BF16 | 音声・画像・テキスト 3モーダル、Apache 2.0 |
| エージェント | Google ADK + LiteLLM | function calling 標準、モデル切替可 |
| VAD | silero-vad | 軽量・常時稼働 |
| TTS | VOICEVOX Engine 0.25.2 ARM64 | 自然な日本語、43話者 |
| TTS fallback | pyopenjtalk + Nitech HTS | VOICEVOX不調時 |
| 短期記憶 | Python deque(maxlen=5) | 同プロセス内、起動毎リセット |
| 長期記憶 | SQLite + sqlite-vec + gemini-embedding-001 | ローカルDB + クラウド埋込 (768d) |
| 家電 | SwitchBot v1.1 API(7デバイス) | Hub Mini でIR家電含む |
| SNS | Bluesky atproto / Moltbook | Bluesky 動作確認済 |
状態機械
5状態 · LED色 · LCD吹き出し · 遷移条件
stateDiagram-v2
direction LR
[*] --> IDLE : 起動
IDLE --> LISTENING : マイク開放
LISTENING --> RECORDING : VAD 3block or ボタン
RECORDING --> THINKING : 1秒無音 / 10秒経過
THINKING --> SPEAKING : 意味ある応答
THINKING --> LISTENING : skip / JSON漏れ
SPEAKING --> LISTENING : 再生終了
| 状態 | LED | LCD | 遷移 |
|---|---|---|---|
| IDLE | 暗青 呼吸 | 「高所より人間を観察中である」 | → LISTENING |
| LISTENING | 明青 | 「声を待っておる」 | → RECORDING |
| RECORDING | 赤 | 「聞いておるぞ…」 | → THINKING |
| THINKING | 黄 | 「聞いた: <書き起こし>」 | → SPEAKING / LISTENING |
| SPEAKING | 緑 | 応答テキスト | → LISTENING |
会話フロー
1ターンのデータフロー — 録音から発話まで
sequenceDiagram
actor U as ユーザー / Button
participant VAD as silero-vad
participant SM as State Machine
participant LLAMA as llama-server
participant ADK as ADK Agent
participant TOOLS as Tools x6
participant TTS as VOICEVOX
participant LCD as LCD + LED
U->>VAD: 発話 or ボタン押下
VAD->>SM: speech_start
SM->>LCD: RECORDING(赤)
VAD->>SM: speech_end(無音1s / 10s)
SM->>LCD: THINKING(黄)
SM->>LLAMA: 16kHz WAV base64
LLAMA-->>ADK: 日本語テキスト
ADK->>LLAMA: テキスト + tools=[6]
loop ツール呼び出し
LLAMA-->>ADK: tool_calls
ADK->>TOOLS: 実行
TOOLS-->>ADK: 結果
ADK->>LLAMA: 結果 + continue
end
LLAMA-->>ADK: 最終回答
ADK->>TTS: 日本語 1〜3文
SM->>LCD: SPEAKING(緑)
TTS-->>U: 24kHz WAV 再生
SM->>LCD: LISTENING(青)
自律ループ — autonomous.py
flowchart TD
S(["起動 60秒待機"])
B{"busy?"}
SK["20秒スキップ"]
R["reset_session()"]
P["OBSERVATION_PROMPT"]
RS{"出力タイプ"}
SOC["broadcast social Bluesky / Moltbook"]
VOI["broadcast voice VOICEVOX"]
SIL["沈黙 skip"]
W(["15〜90分スリープ"])
S --> B
B -->|Yes| SK --> B
B -->|No| R --> P --> RS
RS -->|social| SOC --> W
RS -->|voice| VOI --> W
RS -->|skip| SIL --> W
W --> B
ツール(6個)
tools.py — ADK Agent が呼び出す全ツール
observe(target)
センサ読取・カメラ描写・家電一覧・PTZ首振り
"room""view""devices""meter:NAME""look:DIR"
control_device(name, action, ...)
SwitchBot 7デバイス + Hub Mini IR を1関数で統合制御
"on"/"off""brightness""curtain""color""aircon"
remember(query, limit)
SQLite + sqlite-vec ベクトル類似検索で過去会話を想起
gemini-embedding-001768次元
activity(op, ...)
人間活動 DB の CRUD
"record""list""search""get""update""delete"
broadcast(channel, text)
外部発信チャネルへの統合インターフェース
"voice""social""alexa_say""alexa_routine"
web_search(query)
Tavily → Brave → DuckDuckGo フォールバックチェーン
TavilyBraveDDG
ストレージ
~/.neko/memory.db · SQLite + sqlite-vec
★ conversations + conv_vec(長期記憶)
CREATE TABLE conversations ( id INTEGER PRIMARY KEY AUTOINCREMENT, ts REAL NOT NULL, user TEXT NOT NULL, assistant TEXT NOT NULL ); CREATE VIRTUAL TABLE conv_vec USING vec0( embedding float[768] -- gemini-embedding-001 );
★ activities(人間活動DB)
CREATE TABLE activities ( id INTEGER PRIMARY KEY AUTOINCREMENT, ts REAL NOT NULL, activity TEXT NOT NULL, -- working/eating/sleeping/... description TEXT, location TEXT, duration_min INTEGER, mood TEXT, evidence TEXT, confidence REAL NOT NULL DEFAULT 0.7 );
デプロイ
systemd 4サービス · 運用コマンド
| サービス | ポート | 役割 |
|---|---|---|
| llama-server.service | :8080 | Gemma 4 E2B 推論エンジン |
| voicevox-engine.service | :50021 | VOICEVOX TTS ずんだもん |
| neko.service | :4001 | メインアプリ + Web API |
| neko-bt-autoconnect.service | BT | Echo Dot 自動再接続 |
# Pi接続 ssh neko-pi # 同期 rsync -avz --exclude='.git' --exclude='venv' ./ neko-pi:~/neko/ # 再起動 sudo systemctl restart neko.service # ログ sudo journalctl -u neko.service -f