AutoGen Studioではじめるエージェント検証
はじめに
AutoGenというAIエージェントの作成とエージェント同士の連携が試せるフレームワークがあります。
SDKとしてPythonでエージェントを作ることができますが、ノーコードでエージェントのワークフローを考えたり、エージェント自体の定義、モデルの組み合わせなどが検証できる、AutoGen Studioというアプリがあり、まずはAutoGen Studioでクイックにエージェントの設計をした方が良いかと思います。
今回は特定企業の企業価値について、日本の経済動向を絡めてレポートしてくれるエージェントを作りたいと思います。
AutoGen Studioのインストール~起動
こちらの手順に沿って実行します。
python3 -m venv .venv
source .venv/bin/activate
pip install -U autogenstudio
npm install -g gatsby-cli
npm install --global yarn
cd frontend
yarn install
yarn build
autogenstudio ui --port 8081 --appdir ./app
ここで、autogenstudioのバージョンを確認すると下記のようになっていました。
pip show autogenstudio
Version: 0.1.5
Buildタブに移動すると、Skills、Models、Agents、Workflowsのメニューがあります。
エージェント作成までの流れ
モデル登録
既存のモデルにキー情報を登録しても良いですし、Azure OpenAIモデルを使用する場合は、
new modelから設定します。
AI Foundryでモデルをデプロイして、キー情報、BaseURL、API-versionを入れます。
※モデルのバージョンではなく、APIのバージョンです。
エージェント作成
Agent作成にもパターンがあり、User Proxy Agent、Assistant Agent、Group Chatの3つがStudioでは選べます。
ちなみにAutoGenのSDKで用意されているAgentクラスとしては他にもあります。
UserProxyAgentとAssistantAgentの使い分けはGPT-o1に聞いたら、下記と答えてくれました。
## シンプルなチャットボット
UserProxyAgent: ユーザーの入力を受け付け、AssistantAgentへ転送。
AssistantAgent: 実際の応答(LLM生成)を返す。
チャットUI上では、ユーザーの発言がUserProxyAgent経由でAssistantAgentに届き、AssistantAgentからの応答がユーザーに返される。
## マルチエージェントシステム
UserProxyAgent が「ユーザー入力」を解析し、
「AIアシスタント向けのテキスト生成リクエスト」として AssistantAgent に渡す場合
「ツール呼び出しが必要」と判断し ToolAgent にAPI呼び出しを行わせる
複数のAssistantAgent(複数LLM)を切り替えつつやり取りなど、複雑なフローを構築できる。
AutoGen Studioの画面で設定できる項目は同じで、今回はエージェント同士がやり取りするのではなく、分析ワークフローを作ってみたいのでAssistantだけ使います。
ワークフローとエージェントの役割を考える
ワークフローとはModelsやAgentsと同階層にあり、Agentsをシーケンシャルに実行するか、UserProxyAgentとAssistantAgentのやり取りで実行するかが設定できます。
このようなファシリテーターみたいなAgentと経済動向を取得するAgentが対話型で分析するのも良いかと思います。
こちらでも、場合によっては分析っぽいことをしてくれるのですが、Webでのデータ取得をエージェントに任せすぎると、対話数も増えた上に必ずしも意図通りの結果にならないなと。
初手で試してみるのは良いですが、安定して結果が欲しい場合は、エージェントの分割とエージェントへの指示を細かくしていく必要があると思いました。
今回は、下記のような4つのエージェントをシーケンシャルに繋ぎます。
エージェントの分割とプロンプトの変更、データの保存などは雑な指示でやってみて、
提案されたコードをベースに、正確にデータが取得できない場合にデータを用意したり、同じことを繰り返すところの指示を明確にしたりした結果です。
Agent1:特定企業のニュースを取得
作成したエージェントやワークフローは、jsonでExport/Importできます。
{
"user_id": "guestuser@gmail.com",
"version": "0.0.1",
"type": "assistant",
"config": {
"name": "company_news",
"description": "特定の企業のニュース、PRをweb検索します。",
"llm_config": {
"config_list": [],
"temperature": 0.1,
"timeout": 600,
"cache_seed": null,
"max_tokens": 4000
},
"human_input_mode": "NEVER",
"max_consecutive_auto_reply": 20,
"code_execution_config": "local",
"system_message": "あなたは、特定企業のニュースをウェブから取得するエージェントです。\nコーディング技術と言語スキルを活用し、ユーザの意図を満たすために必要な作業を行ってください。\n\n情報収集が必要な場合\n\nPythonコード (pythonのコードブロック) またはシェルスクリプト (shのコードブロック) を提案し、実行することで\nWeb検索やWebページの内容取得、ファイルのダウンロード/読み取り、現在の日付/時刻の確認、OSの種類の確認など\n\nヘッドウォータースのニュースの場合、下記のファイルから\n/xxxx/headwaters_2024_ir_news.csv\n\n日付とニュースタイトルを返却する",
"default_auto_reply": ""
},
"task_instruction": null
}
不思議なsystem_messageになっていますが、元々のコード実行してwebから取得してくる指示を一部改修して、事前にデータ取得したcsvからデータだけ返却してよということにしました。
ちなみに、生成されたpythonファイルに少し手を加えてcsvファイルは下記のコードで作成します。
import csv
from bs4 import BeautifulSoup
from requests_html import HTMLSession
def main():
session = HTMLSession()
url = "https://www.headwaters.co.jp/ir/news/?yr=2024&tp=0"
r = session.get(url)
r.html.render(timeout=20) # デフォルト3秒なので足りなければ増やす
# 取得したHTMLを解析
rendered_html = r.html.html
soup = BeautifulSoup(rendered_html, "html.parser")
results = []
# "ir-list"クラスを持つdivの下に並ぶ <dl> それぞれに対して処理
ir_list = soup.find("div", class_="ir-list")
if not ir_list:
return results # 見つからない場合、空リスト
dl_elements = ir_list.find_all("dl")
for dl in dl_elements:
dt_tag = dl.find("dt")
dd_tag = dl.find("dd")
if dt_tag and dd_tag:
date_text = dt_tag.get_text(strip=True) # e.g. "2024.12.27"
a_tag = dd_tag.find("a")
title_text = a_tag.get_text(strip=True) if a_tag else ""
# 必要に応じてリンク(URL)も取りたいなら
link = a_tag["href"] if (a_tag and "href" in a_tag.attrs) else None
# 結果を辞書にまとめる
results.append({"date": date_text, "title": title_text, "url": link})
csv_filename = "headwaters_2024_ir_news.csv"
print(f"Saving data to CSV: {csv_filename}")
with open(csv_filename, mode="w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["Date", "Title"]) # header
for item in results:
writer.writerow([item["date"], item["title"]])
if __name__ == "__main__":
main()
Agent2:企業名から証券コードを取得
これは、参考URLとかなくても取得できそうな気がします。
{
"user_id": "guestuser@gmail.com",
"version": "0.0.1",
"type": "assistant",
"config": {
"name": "get_company_code",
"description": "企業名から証券コードを取得する",
"llm_config": {
"config_list": [],
"temperature": 0.1,
"timeout": 600,
"cache_seed": null,
"max_tokens": 4000
},
"human_input_mode": "NEVER",
"max_consecutive_auto_reply": 25,
"code_execution_config": "local",
"system_message": "特定の企業名から下記のサイトなどから証券コードを取得し、返却する\nhttps://www.google.com/finance/quote/4011:TYO"
},
"task_instruction": null
}
Agent3:証券コードから対象企業の株価や日経平均株価、為替を取得
{
"user_id": "guestuser@gmail.com",
"version": "0.0.1",
"type": "assistant",
"config": {
"name": "economy_researcher",
"description": "直近1年の日本の経済動向を調査します。",
"llm_config": {
"config_list": [],
"temperature": 0.1,
"timeout": 600,
"cache_seed": null,
"max_tokens": 4000
},
"human_input_mode": "NEVER",
"max_consecutive_auto_reply": 20,
"code_execution_config": "local",
"system_message": "あなたは、日本の経済動向をウェブから取得したり、特定企業の過去の企業価値を検索するといったタスクを、以下の流れに沿って解決できるエージェントです。\nコーディング技術と言語スキルを活用し、ユーザの意図を満たすために必要な作業を行ってください。\n\nPythonコード (pythonのコードブロック) またはシェルスクリプト (shのコードブロック) を提案し、実行することで\nWeb検索やWebページの内容取得、ファイルのダウンロード/読み取り、現在の日付/時刻の確認、OSの種類の確認など\nコードによって十分な情報が得られたら、言語スキルを使ってタスクを完結させてください。\n\n証券コードから下記のファイルから1年の動向を取得\n\n/xxx/headwaters_stock_data.csv\n\n日経平均株価を取得\n/xxx/nikkei_stock_data.csv\n\n日米の為替を取得\n/xxx/kawase_stock_data.csv\n\n以上のcsvから企業価値の動向と経済動向を比較し、特徴をマークダウンで返却する",
"default_auto_reply": ""
},
"task_instruction": null
}
こちらもAgent1と同様、webから取得できる場合もあるが、失敗する場合もあるので、事前にデータ取得しました。
※headwaters_stock_data.csvとしてしまったので、このワークフローはAgent2の結果を受けたものになっていません。この処理は証券コードからコード実行で取得すべきだと思います。
ちなみに、下記のようなPythonファイルでcsvは作成しました。
import yfinance as yf
import pandas as pd
ticker = "4011.T" # 日本株の場合、".T"を付ける、ヘッドウォータースの株価
ticker = "1321.T" # 日経平均株価ではないが、日経225連動型上場投資信託を参考にする
ticker = "JPY=X" # 為替
# 過去1年間の株価データを取得
data = yf.download(ticker, start="2024-01-01", end="2025-01-01")
# データをCSVに保存
data.to_csv("xxx_stock_data.csv")
※日経225連動型上場投資信託は、東証プライム市場に上場する日本を代表する225社の平均株価の値動きに連動する上場投資信託(ETF)です。
Agent4:対象企業の企業価値についてレポート
{
"user_id": "guestuser@gmail.com",
"version": "0.0.1",
"type": "assistant",
"config": {
"name": "company_value_analist",
"description": "対象企業の去年の経済動向とその根拠を推察する",
"llm_config": {
"config_list": [],
"temperature": 0.1,
"timeout": 600,
"cache_seed": null,
"max_tokens": 4000
},
"human_input_mode": "NEVER",
"max_consecutive_auto_reply": 20,
"code_execution_config": "none",
"system_message": "特定企業の過去の企業価値の動向と日本の経済動向を加味して、特定企業の企業価値の変動について、動向をまとめてください。\nその動向が日本経済による影響か、企業独自のPR活動によるものなのか判断して。\nまた、その根拠を答えてください。"
},
"task_instruction": null
}
このエージェントは不要だったかもしれないです。
Agent3のマークダウンのアウトプットと違いがないなと思いましたが、一応それぞれの結果を残します。
ワークフロー実行結果
ワークフローはplaygroundでセッションを作成して実行できます。
入力欄にヘッドウォータースと入力します。
Agent3の出力
import matplotlib.pyplot as plt
# 日付をdatetime型に変換
headwaters_trend = headwaters_data[['Date', 'Close']].copy()
headwaters_trend['Date'] = pd.to_datetime(headwaters_trend['Date'])
headwaters_trend.set_index('Date', inplace=True)
nikkei_trend = nikkei_data[['Date', 'Close']].copy()
nikkei_trend['Date'] = pd.to_datetime(nikkei_trend['Date'])
nikkei_trend.set_index('Date', inplace=True)
kawase_trend = kawase_data[['Date', 'Close']].copy()
kawase_trend['Date'] = pd.to_datetime(kawase_trend['Date'])
kawase_trend.set_index('Date', inplace=True)
# プロットの設定
plt.figure(figsize=(14, 7))
# ヘッドウォータースの企業価値
plt.plot(headwaters_trend.index, headwaters_trend['Close'], label='ヘッドウォータース', color='blue')
# 日経平均株価
plt.plot(nikkei_trend.index, nikkei_trend['Close'], label='日経平均株価', color='orange')
# 為替レート
plt.plot(kawase_trend.index, kawase_trend['Close'], label='為替', color='green')
# グラフの設定
plt.title('ヘッドウォータースの企業価値と経済動向の比較')
plt.xlabel('日付')
plt.ylabel('価格')
plt.legend()
plt.grid()
plt.show()
日本語文字化けしているのと、為替のスケールが小さくてよくわかりませんが、グラフを出してくれました。
また、マークダウンでのまとめ
このコードを実行すると、ヘッドウォータースの企業価値、日経平均株価、日米の為替の動向を比較したグラフが表示されます。
最後に、得られた情報を基に特徴をマークダウン形式でまとめます。
## ヘッドウォータースの企業価値と経済動向の比較
### 企業価値の動向
ヘッドウォータースの株価は、特定の期間において上昇または下降の傾向を示しました。
企業の成長や市場の影響を受けて、株価が変動しました。
### 日経平均株価の動向
日経平均株価は、国内経済の動向を反映しており、企業価値と相関関係が見られました。
### 日米の為替の動向
USD/JPYの為替レートは、国際的な経済状況や政策の影響を受けて変動しました。
為替レートの変動は、輸出入企業にとって重要な要素です。
## 比較分析
ヘッドウォータースの企業価値は、日経平均株価と一定の相関関係が見られました。
為替レートの変動は、企業の国際競争力に影響を与える可能性があります。
このように、企業価値の動向と経済動向を比較し、特徴をまとめました。必要に応じて、さらに詳細な分析を行うことも可能です。
Agent4の出力
「ヘッドウォータース」の企業価値の動向を日本経済の動向と企業独自のPR活動の観点から分析します。
## 企業価値の動向
「ヘッドウォータース」は、近年、特にデジタル領域での成長が見られ、企業価値が上昇しています。具体的には、以下のような要因が影響しています。
デジタルトランスフォーメーションの進展: 日本全体でデジタル化が進む中、ヘッドウォータースはそのニーズに応えるサービスを提供しており、企業価値の向上に寄与しています。
PR活動の強化: 企業は積極的に自社のサービスや技術をアピールするPR活動を行っており、これが市場での認知度向上に繋がっています。特に、業界イベントやセミナーへの参加、メディア露出が増加しています。
経済動向の影響: 日本経済全体が回復基調にある中で、特にIT関連企業は恩恵を受けやすく、ヘッドウォータースもその一環として成長しています。特に、コロナ禍以降のリモートワークやオンラインサービスの需要増加が追い風となっています。
## 影響の判断
企業価値の変動は、日本経済の動向と企業独自のPR活動の両方の影響を受けていると考えられます。
日本経済の影響: 日本全体のデジタル化の進展や経済回復は、ヘッドウォータースの成長を後押ししています。特に、IT関連の需要が高まっていることが企業価値の向上に寄与しています。
企業独自のPR活動の影響: ヘッドウォータースの積極的なPR活動は、企業のブランド力を高め、投資家や顧客の関心を引く要因となっています。特に、業界内での認知度向上は、企業価値に直接的な影響を与えています。
## 根拠
データ分析: ヘッドウォータースの株価と日本の経済指標(例えば、Nikkei 225やGDP成長率)を比較した結果、株価は経済指標と相関関係が見られました。
ニュース記事の傾向: 最近のニュースでは、ヘッドウォータースが新しいプロジェクトやパートナーシップを発表しており、これが市場での評価を高める要因となっています。
以上のように、ヘッドウォータースの企業価値の変動は、日本経済の動向と企業独自のPR活動の両方によるものであると判断できます。
まとめ
試行錯誤して、ワークフローとエージェントを作成してみました。
結果があっているのかはよくわかりませんが、ワークフローとエージェントの設計をする上で、AutoGen Studioは有効だと思いました。
Discussion