Agent (Python)

役割

AgentはStarnionのAIの脳です。Pythonで書かれており、LangGraph ReActアーキテクチャ上で動作します。GatewayからのgRPCリクエストを受け取り、AIの推論とスキルの実行、メモリの取得を行い、最終的な応答を返します。

コアの役割:

  • ユーザーメッセージを分析して意図を理解する
  • 適切なスキル(ツール)を選択して実行する
  • 4層メモリシステムを検索して関連情報を取得する
  • マルチLLMルーティング(ユーザー設定に基づいてモデルを選択)
  • gRPCストリーミングを通じてリアルタイム応答を配信する

LangGraph ReActアーキテクチャ

AgentはLangGraphのReAct(Reasoning + Acting)パターンを使用します。

ユーザーメッセージ
      │
      ▼
┌─────────────────────────────────────────┐
│           ReActループ                    │
│                                         │
│  ┌──────────┐    思考                   │
│  │  LLM     │──────────────────────┐   │
│  │(推論)   │                     │   │
│  └──────────┘                      ▼   │
│       ▲              ┌─────────────────┐│
│       │ 観察          │ スキル選択       ││
│       │              │(ツール選択)    ││
│  ┌────┴───────┐      └────────┬────────┘│
│  │ スキル     │               │ 実行     │
│  │ 結果       │◄──────────────┘         │
│  │(ツール結果)│                        │
│  └────────────┘                         │
│                                         │
│  [繰り返し:追加スキルが必要な場合は続行]  │
└─────────────────────────────────────────┘
      │ 最終応答が決定
      ▼
   gRPCストリーミング応答

動作フローの概要

  1. 入力の受信:GatewayからgRPCリクエストを受信(ユーザーメッセージ + 会話ID + ユーザーID)
  2. コンテキストの読み込み:会話履歴、ユーザープロフィール、現在のペルソナを読み込む
  3. メモリ検索:関連情報を4層メモリで検索(pgvector類似性検索)
  4. LLM推論:システムプロンプト + 会話履歴 + メモリコンテキストをLLMに渡す
  5. スキル実行:LLMが必要なスキルを選択したら、対応する関数を実行する
  6. ループ:スキル結果に基づいて追加推論が必要な場合はループを繰り返す
  7. ストリーム応答:最終的な回答をgRPCストリームでリアルタイムに送信する
  8. メモリの保存:会話内容をデイリーログに記録する

メッセージ処理フロー

ユーザー入力:「今月の食費はいくら?」
      │
      ▼
[意図を特定]
  → 「費用照会」の意図を検出
      │
      ▼
[メモリ検索]
  → 関連する費用データを検索(レイヤー4:SQL)
  → 以前の類似の質問をメモリで検索(レイヤー1:pgvector)
      │
      ▼
[スキル選択]
  → get_finance_summary(category="food", period="this_month") を呼び出す
      │
      ▼
[スキル実行]
  → DBから今月の食費取引を集計
  → 結果:{"total": 23450, "transactions": [...]}
      │
      ▼
[LLM最終応答生成]
  → 「今月の食費は23,450円です。先月(19,800円)比18%増です。」
      │
      ▼
[gRPCストリーミング]
  → 応答トークンをリアルタイムでGatewayにストリーミング
      │
      ▼
[メモリの保存]
  → この会話をデイリーログに記録

マルチLLMルーティング

Agentは、ユーザーごとに登録されたLLMプロバイダーと現在選択されているペルソナに基づいて、どのモデルを呼び出すかを決定します。

モデル選択の優先順位

1. 現在の会話で明示的に選択されたモデル
      ↓ (なければ)
2. 現在のペルソナにリンクされたモデル
      ↓ (なければ)
3. ユーザーのデフォルトプロバイダーの最初のアクティブなモデル
      ↓ (なければ)
4. システムデフォルト(Gemini Flash)

対応プロバイダー

プロバイダー 実装
Gemini google-generativeai SDK
OpenAI openai SDK(ChatCompletion API)
Anthropic anthropic SDK(Messages API)
Z.AI OpenAI互換エンドポイント
カスタム OpenAI互換ベースURL

4層メモリシステム

Agentは4つのレイヤーで構成されるメモリシステムを通じてユーザーコンテキストを管理します。

┌─────────────────────────────────────────────────────┐
│                 4層メモリ                            │
│                                                     │
│  レイヤー1:デイリーログ                             │
│  ┌──────────────────────────────┐                   │
│  │ pgvector、768次元埋め込み    │                   │
│  │ 会話記録、                   │                   │
│  │ 感情、キーワード             │                   │
│  └──────────────────────────────┘                   │
│                 ↑ 類似性検索                        │
│  レイヤー2:ナレッジベース                           │
│  ┌──────────────────────────────┐                   │
│  │ pgvector、768次元埋め込み    │                   │
│  │ ユーザーの好み、             │                   │
│  │ 学習したパターン             │                   │
│  └──────────────────────────────┘                   │
│                 ↑ 類似性検索                        │
│  レイヤー3:ドキュメントセクション                   │
│  ┌──────────────────────────────┐                   │
│  │ pgvector、768次元埋め込み    │                   │
│  │ アップロードされたドキュメント│                   │
│  │ のチャンク                   │                   │
│  └──────────────────────────────┘                   │
│                 ↑ SQLクエリ                         │
│  レイヤー4:最近の財務                               │
│  ┌──────────────────────────────┐                   │
│  │ PostgreSQL SQL               │                   │
│  │ 過去30日間の取引             │                   │
│  └──────────────────────────────┘                   │
└─────────────────────────────────────────────────────┘

レイヤー1:デイリーログ

  • ストア:PostgreSQL + pgvector拡張機能
  • 埋め込み次元数:768(Gemini text-embedding-004
  • コンテンツ:会話内容、感情状態、重要なキーワード、サマリー
  • 検索方法:コサイン類似性ベースのセマンティック検索
  • ユースケース:「前回何を言ったっけ?」のような過去の会話の想起

レイヤー2:ナレッジベース

  • ストア:PostgreSQL + pgvector
  • 埋め込み次元数:768
  • コンテンツ:ユーザーの好み、繰り返しのパターン、学習したパーソナライズデータ
  • ユースケース:「ユーザーはコーヒーが好き」や「毎月25日に給料が入る」などのパーソナライゼーションコンテキスト

レイヤー3:ドキュメントセクション

  • ストア:PostgreSQL + pgvector
  • 埋め込み次元数:768
  • コンテンツ:ユーザーがアップロードしたPDF、Wordドキュメントなどのチャンク
  • チャンキング方法:セマンティック単位に分割(デフォルト512トークン)
  • ユースケース:「アップロードした契約書の違約金条項を探して」

レイヤー4:最近の財務

  • ストア:PostgreSQL(プレーンSQL、ベクターなし)
  • コンテンツ:過去30日間の取引
  • 検索方法:SQL集計クエリ
  • ユースケース:「今月の食費はいくら?」、「昨日カフェの費用はあった?」

埋め込み

すべてのベクター埋め込みにはGoogleの text-embedding-004 モデルを使用しています。

項目
モデル text-embedding-004
次元数 768
類似性関数 コサイン類似性(<=> 演算子)
言語 日本語を含む多言語

埋め込み生成フロー:

テキスト入力
    │
    ▼
Gemini Embedding APIを呼び出す
    │
    ▼
768次元浮動小数点ベクターを返す
    │
    ▼
PostgreSQL pgvectorカラムに保存
(例:VECTOR(768))

gRPCインターフェース

Agentはデフォルトポート 50051 でgRPCサーバーとして動作します。

サービス定義(protobuf)

service AgentService {
  // 単項チャットリクエスト/レスポンス
  rpc Chat(ChatRequest) returns (ChatResponse);

  // サーバーストリーミング:応答トークンをリアルタイムで送信
  rpc ChatStream(ChatRequest) returns (stream ChatStreamResponse);
}

通信フロー

Gateway (Go)                    Agent (Python)
    │                               │
    │── ChatRequest ──────────────►│
    │   (message, user_id,          │
    │    conversation_id,           │  ReActループが実行
    │    context, files)            │  スキル実行
    │                               │
    │◄── ChatStreamResponse ────────│ (トークンごとのストリーミング)
    │◄── ChatStreamResponse ────────│
    │◄── ChatStreamResponse ────────│
    │         ...                   │
    │◄── [ストリーム終了] ──────────│

Gatewayはストリーミング応答を受け取り、WebSocketまたはSSE(Server-Sent Events)を通じてクライアントに配信します。


スキル実行メカニズム

スキルはLangChainツールとして実装されています。LLMがどのスキルをどのパラメータで呼び出すかをJSON形式で決定すると、Agentは対応するPython関数を実行します。

スキルカテゴリー

カテゴリー スキル例
財務管理 取引の追加/表示、予算確認、統計
スケジュール Googleカレンダー連携
メモ メモの作成/表示/削除
日記 日記の書き込み/表示
目標 目標の設定/チェックイン/評価
Dデイ Dデイの登録/表示
ドキュメント ドキュメント検索、PDFの要約
ウェブ検索 Tavily、Naver Search API
天気 現在の天気検索
電卓 数式の計算
翻訳 多言語翻訳

スキルの有効化

スキルはユーザーごとに有効/無効を設定できます。無効化されたスキルはLLMのツールリストに含まれないため、まったく呼び出せません。

設定 → スキルのトグルか、API POST /api/v1/skills/:id/toggle で制御します。


Docker設定

Agentは docker/Dockerfile.agent を使用し、docker-compose.yml に以下のように定義されています。

agent:
  build:
    context: ../agent
    dockerfile: ../docker/Dockerfile.agent
  container_name: starnion-agent
  ports:
    - "${GRPC_PORT:-50051}:50051"  # gRPCサーバー
  environment:
    DATABASE_URL: postgres://...   # PostgreSQL接続
    GRPC_PORT: 50051
  depends_on:
    postgres:
      condition: service_healthy

AgentはPostgreSQLが準備できた後に起動します。GatewayはAgentが起動した後に接続を試みます。


技術スタックの概要

項目 選択 バージョン
言語 Python 3.13+
AIオーケストレーション LangGraph 0.4+
LLMクライアント langchain-google-genai、langchain-anthropic、langchain-openai latest
会話状態ストレージ langgraph-checkpoint-postgres 2.0+
DBドライバー psycopg (psycopg3) + psycopg-pool 3.2+
gRPCサーバー grpcio 1.70+
画像生成/分析 google-genai (Gemini) 1.0+
ドキュメント解析 pypdf、python-docx、openpyxl、python-pptx latest
ウェブ検索 tavily-python 0.5+
ブラウザ自動化 playwright 1.40+
QRコード qrcode[pil] 8.0+
PDF生成 reportlab 4.4+

スキルアーキテクチャ

各スキルは独立したPythonパッケージとして実装されています。

agent/src/starnion_agent/skills/
├── finance/          # 費用管理
│   ├── __init__.py   # スキル登録
│   ├── tools.py      # LangChainツール関数の定義
│   └── SKILL.md      # スキルの説明(LLMシステムプロンプトに注入)
├── weather/
│   ├── __init__.py
│   ├── tools.py
│   └── SKILL.md
├── loader.py         # 動的スキルロード
├── guard.py          # スキルアクセス権限チェック
└── registry.py       # 全スキルレジストリ

SKILL.mdの役割

各スキルディレクトリの SKILL.md ファイルはLLMシステムプロンプトに直接注入されます。これにより、LLMは各スキルをいつ、どのように使用するかを正確に認識できます。

システムプロンプト = ベースペルソナ + アクティブなスキルのSKILL.mdコンテンツ

スキルガード

ユーザーによって無効化されたスキルは guard.py でブロックされます。非アクティブなスキルのツールはLLMに公開されないため、まったく呼び出すことが不可能です。


ログとHTTPサーバー

gRPCポート(50051)に加えて、AgentはHTTPサーバー(ポート8082)も実行します。

ポート 目的
50051 gRPCサーバー(Gatewayとの通信)
8082 HTTPサーバー(ログストリーミング、ドキュメントインデックス、検索埋め込み)

Gatewayの /api/v1/logs/agent エンドポイントはAgentのポート8082にプロキシして、リアルタイムのAgentログを提供します。


Copyright © 2025 StarNion. All rights reserved.  |  v0.1.1