【AIエージェント】Profile とは
この記事の概要
AIエージェントは、「Profile」「Memory」「Planning」「Action」から構成されます。
その内の「Profile」について説明します。
さらに、動的プロファイルは文章だけでは想像がつきにくいので、簡単なコーディング例も用意しました。
引用:A Survey on Large Language Model based Autonomous Agents (2023)
AIエージェントのプロファイルとは
「プロファイル」とは、AIエージェントにおいて、役割を定義し、LLMの振る舞いに影響を与えるための情報を指します。
エージェントが特定のタスクを遂行する際に、例えばコーダー、教師、領域エキスパートといった特定の役割を担うことを可能にすることが目的です。プロファイル情報は通常、LLMへのプロンプトとして組み込まれ、その振る舞いを左右します。
静的プロファイル
エージェントの 役割・人格・専門領域などをあらかじめ固定しておくプロファイルです。
最初にシステムプロンプトや設定ファイルに書き込まれ、その後は基本的に変わりません。
静的プロファイルは、FAQや単発タスクなどの単純な実装において、挙動が安定するため、広く利用されています。
具体的には、OpenAIのAPIを利用し、LLMの役割をシステムプロンプトに記述するなどが、静的プロファイルに当たります。
しかし、プロンプト固定の“Persona”だけでは限界があり、「メモリ+履歴更新」を組み込むフレームワーク(動的プロファイル)が主流になっています。
動的プロファイル
実行中に履歴や外部情報を取り込みながら更新されるプロファイルです。
エージェントの運用履歴、ドメイン専門知識、パフォーマンス指標、および応答傾向を捉えるために設計されています。
これはスキル、履歴、埋め込み、可用性という主要な要素から構成されます。
-
スキル
エージェントの事前に宣言された能力や専門分野を表します
-
履歴
最新のタスク結果、完了率、および評価スコアが含まれます。これは固定長ウィンドウ(例:最新10タスク)で更新され、動的な入力としてオーケストレーターに提供されます。
-
埋め込み
エージェントの潜在的な行動特性を要約する学習されたベクトルであり、定期的に更新されます。
-
可用性
エージェントが現在アイドル状態かビジー状態か、および最近の作業負荷レベルをモデル化します。
実装例
チャット形式で、動的プロファイルをLangChainで作ってみます。
システム概要
- 会話とは非同期で情報が動的プロファイルのハンドラーに渡される。
- 動的プロファイルのハンドラーでは、json形式やベクトルなどとして情報が保存される。
- 次の会話でプロンプトを呼び出す時、更新されたプロファイルを利用する。
本来は上記のように実装されるかと思いますが、今回は簡易的な実装ということで、非同期処理については省略します。
環境構築
conda create -n ai_agent_profile python=3.10 -y
conda activate ai_agent_profile
pip install openai langchain langchain_community tiktoken
コーディング例
import os
import json
from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.schema import BaseOutputParser
# ディレクトリ準備
os.makedirs("profiles", exist_ok=True)
os.makedirs("embeddings", exist_ok=True)
# LLM & Embedding モデル
llm = ChatOpenAI(model="gpt-4o")
embedding_model = OpenAIEmbeddings()
# JSON出力パーサー
class JSONParser(BaseOutputParser):
def parse(self, text: str):
return json.loads(text.strip())
# プロンプト
update_prompt = """
あなたはエージェントのプロファイル更新ボットです。
## 現在のプロフィール
{profile}
## 新しいユーザ発話
"{message}"
---
上記を踏まえ、dynamic フィールドに **必要な変更だけ** を適用した
完全な JSON をjson形式で返してください。
"""
# メイン関数
def update_profile(user_id: str, message: str):
# プロファイルファイルの読み書き
profile_path = f"profiles/{user_id}.json"
if os.path.exists(profile_path):
with open(profile_path, "r", encoding="utf-8") as f:
profile = json.load(f)
else:
profile = {}
# LLM による更新プロファイル生成
prompt = update_prompt.format(
profile=json.dumps(profile, ensure_ascii=False),
message=message
)
resp = llm.invoke(prompt)
try:
content = resp.content.removeprefix("```json").removesuffix("```")
print(content)
new_profile = JSONParser().parse(content)
except Exception as e:
print("[ERROR] Failed to parse JSON from LLM output:")
print(resp.content)
raise e
# プロファイルを保存
with open(profile_path, "w", encoding="utf-8") as f:
json.dump(new_profile, f, indent=2, ensure_ascii=False)
# 発話のベクトル生成 & 保存
vector = embedding_model.embed_query(message)
embedding_path = f"embeddings/{user_id}_latest.json"
with open(embedding_path, "w", encoding="utf-8") as f:
json.dump({
"user_id": user_id,
"text": message,
"embedding": vector
}, f, indent=2, ensure_ascii=False)
-
次の関数を実行します。
update_profile("u123", "最近はDifyに興味があります。")
すると、profiles/ディレクトリの中に、次のjsonファイルが生成されます。( u123.json )
{ "interest": "Dify" }
-
動的プロファイルが更新する様子を観察します。
update_profile("u123", "最近はn8nにも興味があります。")
u123.jsonが次のようになりました。
{ "interest": "Dify, n8n" }
-
最後に、もう一度動的プロファイルが変更される様子を観察します。
update_profile("u123", "n8nへの興味がなくなりました。私は男性ですが、仕事のために健康を意識したいです。おすすめを教えてください。")
u123.jsonが次のようになりました。
{ "interest": "Dify", "gender": "男性", "healthConscious": true }
簡易的な実装でしたが、AIエージェントの動的プロファイルがこのように変更されていくというイメージが掴めたのではないでしょうか?
まとめ
AIエージェントの構成要素の1つである「Profile」について説明しました。
静的プロファイルは通常のプロンプトであり、それに対して動的プロファイルは処理に中でプロンプトが変更されるような仕組みを指します。
動的に変更されるイメージが湧きにくいと思うので、簡易的にLangChainとpostcornを使って、AIエージェントのプロファイルが変更されるコードを作ってみました。
参考
A Survey on Large Language Model based Autonomous Agents (2023)
Discussion