Taste of Tech Topics

Acroquest Technology株式会社のエンジニアが書く技術ブログ

OSS の Open Deep Research で Deep Research を実現してみた

はじめに

こんにちはデータ分析エンジニアの木介です。
今回は、Hugging Faceより公開されたオープンソースのAIエージェントOpen Deep Researchを実際に動かしていきたいと思います。

huggingface.co

1. 概要

Deep Researchとは、ウェブ検索をしながら自律的に情報を収集し、詳細なレポートを出力してくれるサービスのことを指します。
現在、「Deep Research」という名称が付けられている代表的なサービスとして、以下のものがあります。

サービス名 OpenAI
Deep Research
Google Gemini
Deep Research
Perplexity
Deep Research
Open
Deep Research
プロバイダー OpenAI Google Perplexity AI Hugging Face
値段 ChatGPT Pro(月額200ドル)
ChatGPT Plus(月額20ドル)でも回数制限付きで利用可能
Gemini Advanced(月額20ドル) 無料(未登録ユーザーは1日5回制限) 無料(オープンソース
精度 GAIAベンチマーク67%、Humanity's Last Exam26.6%(GPT-4系「o3」採用) 公式ベンチマークなし。高精度な医療・市場調査レポート生成が可能と評価 Humanity's Last Exam21.1%。検索・読解性能が高いが、一部誤りあり オープンモデルの性能に依存(o1モデルを利用することでGAIA55%、Humanity's Last Exam8.5%)
特徴 ChatGPT内で動作。検索・推論を組み合わせた詳細な調査レポートを5~30分で生成 50以上のWebサイトから情報収集。プラン編集、進捗可視化、Googleドキュメント出力が可能 反復検索・推論により短時間で包括的なレポートを生成。検索対象の指定やエクスポート機能あり オープンLLMのみで実行可能。完全オフライン運用やプライバシー保護に適する


上記の中でも今回は特にHugging Faceが開発したオープンソースのOpen Deep Researchについて説明していきたいと思います。
こちらのサービスではOpenAIのDeep Researchの再現を目指しており、OpenAI Deep Researchと同様に大規模言語モデル(LLM)とエージェントフレームワークを組み合わせて情報検索や推論を行うことができます。

huggingface.co

openai.com

OpenAIのDeep Researchは、ウェブ検索を活用しながら複雑な問題に対処するためのツールですが、そのエージェントフレームワークの詳細は非公開となっています。これに対し、Hugging Faceのチームは、オープンな代替手段としてこの「Open Deep Research」を開発し、誰でも利用・改良できるシステムを構築している形となります。

Open Deep Researchの仕組み

Open Deep Researchは、以下の2種類のエージェントが協調して情報検索や推論を行います。

  • CodeAgent
    • ユーザーの質問を受け取り、検索の計画を立案する
    • 検索タスクを別エージェント(SearchAgent)に渡す
  • SearchAgent
    • 実際にウェブ検索を実施し、情報を収集・整理する役割を担当します。

具体的なフローは以下のようになります。

特に、CodeAgent→SearchAgentへの指示の出し方が、以下のようなコードベースとなっており、これにAgentがより複雑なアクションを指示として渡せるようになっています。

Open Deep Research のリクエスト例

search_results = search_agent(task="『Open Deep Research』に関する情報をインターネットで検索して、どのような組織あるいは活動内容なのかを調べてください。")
print(search_results)

2. Open Deep Researchを動かす

では早速、Open Deep Researchを実際に動かしていきたいと思います。

準備

以下の3つのAPIキーを取得します。

  • Hugging Face APIキー

huggingface.co

  • SERPAPI APIキー

www.searchapi.io

  • OpenAI APIキー

platform.openai.com

また今回はo1モデルを利用してDeep Researchを行っていきます。

構築方法

以下の手順で環境を構築します。

git clone https://github.com/huggingface/smolagents.git
cd smolagents/examples/open_deep_research

pip install -r requirements.txt
pip install smolagents[litellm]

export OPENAI_API_KEY="取得したキーを設定"
export HF_TOKEN="取得したHugging Faceのトークン"
export SERPAPI_API_KEY="SERPAPIのキー"

検索実行

以下のコマンドを用いて実行しました。

python run.py --model-id "o1" "Open Deep Researchについて教えてください"

実行プロセス(途中経過)

検索を実行すると、以下のような処理が内部で行われます。

Here is the plan of action that I will follow to solve the task:
```
1. Review the task “Open Deep Researchについて教えてください” and the known facts.
2. Use the search_agent to learn about “Open Deep Research.”
3. Summarize key information from the search results, such as background, objectives, or notable works.
4. Present the findings using final_answer.


```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Step 1 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Output message of the LLM: ────────────────────────────────────────────────────────────────────────────────────────────
Thought: I need to find information about "Open Deep Research." I will ask the search_agent to perform a web search in
Japanese to get relevant information.

Code:
```py
search_results = search_agent(task="『Open Deep
Research』に関する情報をインターネットで検索して、どのような組織あるいは活動内容なのかを調べてください。")
print(search_results)
```
─ Executing parsed code: ────────────────────────────────────────────────────────────────────────────────────────────
search_results = search_agent(task="『Open Deep
Research』に関する情報をインターネットで検索して、どのような組織あるいは活動内容なのかを調べてください。")
print(search_results)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

CodeAgentがSearchAgentにpythonのコードベースでリクエストを送り、それをもとにSearchAgentが検索を行っていることがわかります。

回答結果

得られた回答: 以下に、『Open Deep Research』に関する概要をまとめました。

【概要】
『Open Deep Research』とは、オープンソースのプロジェクトで、AI技術やウェブ検索機能を用いて大量の情報を取り込み、要約や レポート作成、リサーチ業務を支援することを目的としています。GitHub上には複数のリポジトリが存在し、オープンソースとして 開発・改善が進められています。また、公式サイトやデモ版なども公開されており、誰でも導入や拡張が可能です。


【背景・特徴】
・元々は OpenAI が発表した “Deep Research” をベースに、コミュニティ主導で「オープンソース化」された点が特徴です。
・インターネット上に存在する大規模なテキストデータをAIエージェントが検索・解析し、要約やレポートを自動生成する機能を備 えています。
・Firecrawlなどのクローラー技術を組み合わせて検索精度を高めるアプローチも見られます。


【活用例】
・研究資料の自動作成や情報整理など、ウェブ上の膨大な情報を効率的に扱う必要がある場面での利用が想定されます。
・非営利のコミュニティ活動であるため、開発者やユーザーが協力して機能を拡充・改善しながら発展しているとみられます。


【注意点】
・2025年ごろにまとめられた情報がヒットしており、正式な企業組織などは固まっていない可能性があります。実際に利用する場合 は、GitHubリポジトリや公式サイト(https://opendeepresearch.vercel.app など)を確認することを推奨します。
・ライセンス形態や継続的な開発状況についても最新情報をチェックしておくとよいでしょう。


以上が、『Open Deep Research』に関する主な情報です。

最新の情報をもとに、検索対象についてのレポートを生成できました。

OpenAI Deep Researchとの比較

同様の質問をOpenAI Deep Researchに対して行った結果が以下になります。

OpenAI Deep Researchの回答結果

了解しました。「Open Deep Research」の概要について調査し、その目的や活動内容、関連する組織やプロジェクトなどの情報をまとめます。

調査が完了しましたらお知らせします。

# Open Deep Researchの概要


## 概要
Open Deep Research(オープン・ディープ・リサーチ)は、OpenAIが開発した高度な調査エージェント「Deep Research」のオープンソース代替を目指すプロジェクトです。Hugging Face社の共同創業者トーマス・ウルフ氏らが中心となり、**誰もが自分の好きな言語モデルを組み合わせて**ローカル環境で高度な調査エージェントを利用できるようにすることを目的としています。具体的には、OpenAIが公開しなかったエージェント制御部分(ウェブ閲覧やツール使用を指示するフレームワーク)を独自に実装・公開し、閉鎖的な最先端AI機能の民主化を図るミッションを掲げています。


## 主要な研究分野・活動内容
Open Deep Researchは、Deep Researchと同等の**ウェブリサーチ機能**を実現することに焦点を当てています。ユーザーの質問に対し、インターネット上から情報を自動収集・分析し、論理的な推論を行って長文の回答を生成します。その特徴的な機能は次の3点にまとめられます:

  • **コンテンツの発見**: ユーザーの質問に関連する情報をウェブ検索で収集します(自動的に検索クエリを生成し、最新の情報を探索)。
  • **コンテンツの統合**: 複数の情報源から得た内容を要約・統合し、重要なポイントを抽出します。
  • **情報の推論**: 集めた情報に基づいて論理的な推論を重ね、質問に対する結論や詳細な説明を導き出します。

こうしたプロセスにより、**人間が数時間かけて行う調査を数分〜数十分で遂行し**、専門家レベルの詳細なレポートを生成できるとされています。

技術的には、Open Deep Researchは以下の要素を組み合わせて実現されています:

1. **検索エンジン** – 外部の検索サービスを用いて関連情報を検索し、該当ページのURLを取得(例: DuckDuckGo APIなど)
2. **リーダー(Webページ内容抽出)** – 検索結果のURLからページ本文を抽出し、テキストデータ化するモジュール
3. **大規模言語モデル(LLM)** – 抽出したテキストに基づき要約・質問応答・推論を行うAIモデル(現在は主にOpenAIのモデルo1などを利用)
4. **エージェント制御ロジック** – LLMにウェブ閲覧やファイル読込などのツール使用を指示し、複数ステップの操作を管理するフレームワークです。Hugging Face版ではPython製の軽量エージェントライブラリ「**smolagents**」を用いてこのロジックを実装し、OpenAIのLLM(o1モデル)のAPIと組み合わせてDeep Research相当の動作を再現しています。


## 関連する組織やプロジェクト
Open Deep Researchは**Hugging Face社**の研究者チームによって推進されているプロジェクトです。特にトーマス・ウルフ氏(Hugging Face共同創業者)やAymeric Roucher氏らが24時間のハッカソン的取り組みでプロトタイプを構築し、その成果を公開しました。このプロジェクトはOpenAIのDeep Research(元のクローズドなエージェント)に触発されたものであり、オープンソースコミュニティによる協力が特徴です。

同様の目的を持つ関連プロジェクトも複数存在します。例えば、**Jina AI社**はTypeScript/Node.jsで実装された「node-DeepResearch」というオープン版エージェントを開発し、GooglePaLM 2やGeminiモデルをバックエンドに用いるアプローチを取っています。また、個人開発者によるクローン実装も登場しており、Hugging Faceの報告によれば*dzhng*氏や*nickscamara*氏などがそれぞれ独自にDeep Researchのオープンソース版を公開しています。これらの取り組みは相互に刺激を与えあい、エージェントAI分野全体の発展に寄与しています。


## 公式サイトや情報源
Open Deep Researchに関する公式情報やリソースは以下の通りです。

  • **公式ブログ記事(Hugging Faceブログ)** – 2025年2月4日にHugging Faceが公開した記事「*Open-source DeepResearch – Freeing our search agents*」で、Open Deep Researchの背景や実装、成果が解説されています。
  • **デモサイト(Hugging Face Spaces)** – Hugging Faceの提供するデモページ上でOpen Deep Researchを試用できます。ブラウザから質問文を入力すると、エージェントが自動で検索・回答を行います。現在このデモには世界中から多数のリクエストが殺到しており、応答待ち時間が長くなる場合があります。
  • **ソースコードGitHub)** – Open Deep Researchの実装コードは**GitHub**上で公開されており、Hugging Faceの`smolagents`リポジトリ内の`open_deep_research`サンプルとして参照できます。誰でもコードを閲覧・利用でき、Issueやプルリクエストを通じたフィードバックや貢献も歓迎されています。

なお、この他にもTechCrunchやArs Technicaなどのテックメディアが本プロジェクトについて詳細なレポートを公開しており、日本語ではQiitaやGIGAZINEが背景解説やセットアップ方法を紹介しています。


## 最新の研究成果や発表
Open Deep Researchは公開直後から高い性能を示しており、OpenAI公式のDeep Researchに迫る成果が報告されています。具体的には、一般的なAIアシスタントの能力を問う**GAIAベンチマーク**において、Deep Research本家が**平均67.36%**の正解率を達成したのに対し、Open Deep Researchは**54%前後**のスコアに到達したと伝えられています。わずか1日程度で基本機能を再現し、本家の約8割に迫る性能を示したことは大きな成果です。Hugging Faceチームは「これは始まりに過ぎず、改善すべき点はたくさんあります」と述べており、引き続き性能向上に向けた開発を継続する意向を示しています。

その後もOpen Deep Researchは着実にアップデートが加えられています。例えば**2025年3月時点**では、新機能としてエージェントの探索プロセスを視覚的に表現する「**Visual Flow**」機能が導入されており、複数段階にわたる深掘り調査の流れを把握しやすくする工夫がなされています。また、今後の計画として、OpenAIが発表したブラウザ操作エージェント「Operator」に匹敵するような**GUI操作対応エージェント**(画面を見てマウス・キーボードで操作するエージェント)の開発にも取り組むとされています。これらの最新発表から、Open Deep Researchプロジェクトはコミュニティと協力しながら進化を続けており、オープンソースAIエージェントの可能性を広げる最前線に立っていることが伺えます。

以下が簡単な比較になります。

比較項目 Open Deep Research OpenAI Deep Research
参考サイト数 8サイト 17サイト
回答までの時間 約2分 約16分
レポート品質 検索結果を反映しているが簡潔である。 検索結果の詳細にまで触れられている。

結果としては、やはりOpenAI Deep Researchの方がより多くのサイトを参照しており、レポートとしても充実していました。
ただ、Hugging Face の場合、OSSとして公開されているため、任意のLLMを組み合わせたり、自社のサービスなどに組み込むことができるのは良いですね。

まとめ

オープンソースとして公開されているOpen Deep Researchを実際に動かしてみました。
OSSでDeep Researchを構築できることが魅力的だと感じました。
精度についてもOperatorの導入などまだまだ改善を行えそうなので今後のアップデートに注目していきたいです。

NLP2025でポスターとワークショップで発表しました!

皆さんこんにちは
Acroquestのデータサイエンスチーム「AcroYAMALEX」のチームリーダ、@tereka114です。
AcroYAMALEXチームでは、コンペティションへの参加や自社製品開発、技術研究などに日々取り組んでいます。
(詳細はこちらをご覧ください。)

私は長崎で開催されているNLP2025に3/12(木)〜参加していました。
私自身はNLP2025、長崎ともに初でワクワクでした。

会場前のNLP2025看板

NLP2025

言語処理学会」は、言語処理に関する研究を行う日本の学術団体で、自然言語処理、計算言語学、言語情報処理などの分野を扱います。
今回の『言語処理学会 年次大会』は、毎年3月頃に開催され、当該分野における最も重要な学術イベントの一つとして位置づけられています。
端的に言えば、日本語の自然言語処理で大きな学会です。

本年は長崎開催で、2248名の参加がありました。

anlp.jp

今回は当社から2つのポスターとワークショップでの発表をしました。

ポスター発表

今回のポスター発表は次の2点です。

1. 『表記ゆれが文埋め込みモデルに及ぼす影響についての考察』
著者:佐々木峻、山本大輝
論文:https://www.anlp.jp/proceedings/annual_meeting/2025/pdf_dir/P8-5.pdf
論文概要:RAGや文埋め込み検索が台頭する中、日本語検索では表記ゆれが課題となっている。本研究では単語の表記ゆれが文埋め込み検索の精度に与える影響を検証し、同義語辞書によるクエリ変換を用いた新手法を提案・評価する。

表記ゆれが文埋め込みモデルに及ぼす影響についての考察

2. 『少量ショットに対する大規模言語モデル(LLM)を用いた人工データ生成による精度向上の試み』
著者:山本大輝、佐々木峻
論文:https://www.anlp.jp/proceedings/annual_meeting/2025/pdf_dir/Q8-22.pdf
論文概要:LLMは自然言語処理で高い精度を示すが、高コストが課題。従来の手法はコストが低いが、データ不足で性能が向上しない。
本研究では、LLMで学習データを生成し、軽量モデルの精度向上を目指した。実験で、参照なし文書生成プロンプトが最も効果的で、軽量モデルでも精度向上が確認された。

少量ショットに対する大規模言語モデル(LLM)を用いた人工データ生成による精度向上の試み

NLP2025初参加でしたが、当日のポスター発表で参加者の皆様から、様々なフィードバックが得られたので非常に貴重な体験ができたと思っています。
今後の研究活動にも活かせるものもありましたので、更に来年に向けて進展させたいと思います。

大規模言語モデルのファインチューニング技術と評価

当社のメンバーで「大規模言語モデルのファインチューニング技術と評価」のワークショップに参加しました。
このワークショップでは事前にLLMを使って「数学」と「安全性」の2種類のタスクの精度を向上するコンペティションが開催されていました。次のようなタスクです。

  • 数学:与えられた数学の問題を解く
  • 安全性:答えてはいけないものに回答せず、答えて良いものに適切に回答する

llm-jp.github.io

当社のデータサイエンスチーム、「YAMALEX」で参加して、数学準優勝、安全性3位になりました。(以下、表彰状)

数学表彰状
安全性タスク

数学タスクでは論理的な解説とその答えを導くコード生成を含むKaggleのAIMO Prize 1stのソリューションを適用したモデルを開発しました。
また、安全性タスクではCoTのデータを生成し、論理的に答えを導き出すようにモデルを学習しました。
本ソリューションの詳細はこちらにあります。
ワークショップ内では当チームの代表として佐々木が発表しました。

当社YAMALEXチームの発表

安全性、数学タスク両方で論理的な推論をさせるように学習させることで精度向上に繋がることを実感できました。
また、今回のワークショップではモデルの学習に関する知識に関する招待講演があり、非常に学びが多かったです。

その他

長崎は観光も食事もバッチリです。
ちゃんぽん、お寿司などもおいしいところが会場近辺にあります。

ちゃんぽん(中華 大八)

また、観光で空いた時間に出島に行きました。
江戸時代の外交を中心とした当時の特産品、文化などを学べて、非常に面白いと思いました。

出島(ミニ出島の写真)

学会も観光も含めて、非常に満喫できました。

最後に

NLP2025にはじめて参加しましたが、参加者の皆様と様々な議論ができて学びも多かったです。
改めて、運営、スポンサー、参加者の皆様ありがとうございました。
来年の宇都宮も参加したいと思っています。

Acroquest Technologyでは、キャリア採用を行っています。

  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。

www.wantedly.com

Dify v1.0.0 で新登場したエージェントノードで Function Calling を実行

1. はじめに

こんにちは、りょうたです。

先週、ついに待望のDify v1.0.0が正式リリースされて、生成AIを利用したサービスや基盤開発に関わる身として大変ワクワクしております!

github.com

本バージョン注目の機能として、エージェントノード と プラグインシステム が導入されています。

エージェントノードとは、予め定義されている「エージェント戦略」を用いて、質問に応じたツールの呼び出しや複数ステップにわたる推論を自動的に実行する、新しいノードです。

今回は、Dify公式が出しているエージェンティック戦略を用いて、チャットフローを作成してみます。

2. エージェントノードとは

2.1. 基本的な機能

エージェントノードとは、事前に定義されている複数ステップにわたる推論と、ツール実行を行うノードです​。

チャットフローにこのノードを組み込むことで、ユーザーの質問に応じて、動的にツールを選択・呼び出し、推論を行い、複雑なタスクを実行することが可能になります。

Dify公式が用意している「Dify Agent Strategies」というプラグインには、2つのエージェンティック戦略が用意されています。

戦略 概要
Function Calling ユーザーからの質問に応じて、あらかじめ定義した外部関数の中から、どのツールを呼び出すかをAIが判断し、使用する関数名と引数を返してくれる仕組みのこと。別名 Tool Use とも呼ばれている。
ReAct AIが推論(Reasoning)と行動(Action)を交互に実行する手法のこと。思考結果とツール呼び出しの結果を反映して回答を更新していくことで、複雑な問題の解決やタスク自動化を実現する仕組み。

今回は、Function Callingを用いて、ツールの呼び出しを行います。

今回用いるFunction Callingについて、詳細はこちらをご参照ください。

acro-engineer.hatenablog.com

2.2. 従来のワークフローで実現しようとした際との違い

以前は実現したいチャットフローの構成ごとに、全体の設計を行い、ツール選択の実現方法などを検討する必要がありました。

例えば、Function Callingをチャットフローで実現しようとした際は

  1. どうやって適切なツールを選択させるか
  2. どういった条件で、使用するツールを分岐させるか
  3. 分岐した先の処理を考慮して、呼び出し元でどのような情報を渡しておかなければいけないか

などを検討する必要があり、設計や開発、改修などにコストがかかる状態でした。

エージェントノードを用いることで、これらのコストを削減することが出来そうです。

従来のチャットフローでのFunction Calling実現例

2.3. Difyアプリの「エージェント」との違い

従来のエージェントは単一のアプリとして動作し、事前に定義された特定のタスクを単体で実行するアプリでした。

簡潔に言うと、単純なチャットボットに近いものです。

一方で、エージェントノードは、ワークフローの一部として統合され、他の様々なツールと連携して、複雑な処理を実現することが出来ます。

エージェントアプリ

3. エージェントノードを使ってみた

3.1. フローの概要

今回は、食事に関する相談を受け付けるチャットフローを作成していきます。

こちらに今回作成するフローを示します。

今回作成したチャットフロー

主となるチャットフローを作成し、こちらのエージェントノードのFunction Calling戦略を用いて、ツールの振り分け処理を定義します。

質問に応じて、このエージェントノードから、ツールの呼び出しを行う構成です。

今回は、以下の3つのツールを用意しています。

  1. メニュー考案
  2. 栄養士
  3. 一般質問

3.2. Function Callingを用いたフローの構築

ツールの準備

エージェントノードの前に、呼び出し先のツールについて定義しておきます。

エージェントノードから呼び出し可能なツールは、以下の3つです。

  1. プラグイン
  2. カスタムツール
  3. ワークフロー

今回はワークフローを用います。

スタジオの新規作成からワークフローを選択し、以下のようなフローを構築します。

質問文を受け取り、LLMに問い合わせを行うシンプルな構成です。

メニュー考案ワークフロー

メニュー考案のLLMのシステムプロンプトは次のように定義しました。

あなたは、料理の献立を考案し提案する専門のチャットボットです。ユーザーからの質問や希望を受け取り、その内容に応じた最適な料理の献立を提供してください。
ただし、提案する献立は1食分のみです。

役割と目的:
ユーザーの質問や条件に沿った料理の献立を、具体的な料理名、調理方法を提案する。
栄養バランスや調理の手間、季節感、テーマ(和食、洋食、中華など)にも配慮し、利用者のニーズに合わせた献立を考案する。

ユーザーの具体的な条件(食材の制限、アレルギー、予算、調理時間など)が提示された場合は、それらに適合する献立を提案する。

最後に、終了ノードの出力変数に、LLMの回答を設定すれば、ワークフローの構築は完了です。

ツールとして用いるために、公開ボタンを押して、ワークフローを公開状態にします。

ワークフロー公開

作成したワークフローを、エージェントノードで用いるツールとして用いるため、名前などの設定を行います。

「ツール入力」のqueryは、ワークフローの開始ノードで設定している入力フィールドになります。

こちらで設定できるメソッドの項目については、LLMが自動で入力してくれる「LLM入力」と、予め入力する値を自分で定義しておく必要がある「設定」の2つが設定可能です。

今回は、ユーザーからの質問文を受け取るqueryという項目について、Function Callingからの結果を受け取るために、メソッドはLLM入力を設定します。

ツールとしてのワークフロー設定

同様に、「栄養士」「一般質問」についても、以下のシステムプロンプトでワークフローを作成します。

■栄養士

あなたはプロの栄養士として、利用者から送られてくる献立や食事に関する質問に対して、健康や栄養バランスの視点からコメントし、適切なアドバイスを提供する役割を担います。以下の指針に従って回答してください。

# 専門的な視点でアドバイス
献立に含まれる栄養素や食材の特徴、調理方法に基づいた具体的なコメントを行う。
利用者の質問内容や状況に応じたアドバイスを心がけること。
​
# 指針
食材や調理法、栄養バランスについて利用者が理解しやすい言葉で表現する。
献立の改善点や、補完すべき栄養素があれば具体的な提案を行う。
健康維持やダイエット、エネルギー補給など、利用者の目的に沿ったアドバイスを行う。

■一般質問

あなたは優秀なチャットボットとして、ユーザからの様々な質問に回答してください

エージェントノードを設定

チャットフローを選択してアプリを新規作成し、こちらのようにエージェントノードを設定します。

エージェントノード

エージェンティック戦略はFunction Callingを選択します。

モデルはAWS (Bedrock) の「Claude 3 Haiku」を用います。 Function Callingに公式に対応している、OpenAI以外のモデルであっても実行することが可能です。

Tools Listには、先ほど定義した3つのワークフローを定義します。

最後にシステムプロンプトと、ユーザプロンプトを設定します。

システムプロンプト

あなたは、食事に関する質問を受け付けるエージェントシステムのスーパーバイザーエージェントです。
以下のルールと方針に従い、適切なツールの選択を行ってください。

# システム全体の概要
- ユーザーからの食事関連の質問に対して、以下の3種類の専門エージェントを活用する。 
1. **献立考案**:新たなメニューのアイデアや料理の提案を行う。 
2. **栄養士**:栄養バランス、健康面、食材の組み合わせ等の観点からアドバイスを提供する。 
3. **その他の一般質問エージェント**:料理以外の雑多な質問や、料理の豆知識や調理法、食材の選び方など、専門分野に分類されない質問に対応する。

# 注意点
選択できるツールは1つのみです。
呼び出したツールからの応答を基に、情報を全て使って回答を行ってください。
必要に応じて箇条書きにするなど、読みやすく出力してください

# 最終目標
あなたの役割は、ユーザーからの食事に関する質問に対し、各エージェントがその専門分野で最適な回答を提供できる環境を維持し、システム全体として一貫性のある、質の高い情報提供を実現することです。

4. Function Callingを実行してみる

実行結果

フロー全体が完成したので、プレビューで実際に実行してみます。

まずは、メニュー考案に関する質問を行ってみます。

■質問1

肉料理の献立を考えて

結果は以下のようになりました。

ログも確認すると、tool_nameのところに、ツールとしてのワークフロー設定で設定したthink_nameというツールが呼ばれています。

メニュー考案のワークフローを呼んでくれているようです。

さらに、queryの部分を見ると、「肉料理の献立」というテキストが入力されています。

質問文から、ツールに渡す適切なテキストを抽出して、ツールに渡してくれているようです。

メニュー考案

料理以外のことについても質問してみました。

■質問2

富士山の標高を教えて

こちらも、一般質問を呼び出してくれているようです。

一般質問

対応するツールが存在しない場合はどうなる?

質問に対応する適切なツールが存在しない場合は、どのように動作するのでしょうか。

エージェントノードの「一般質問」を無効化した上で、もう一度富士山の標高に関する質問を行いました。

まず、エージェントノードの設定画面で、「一般質問」を無効化します。

一般質問無効化

この状態で、以下の質問を行います。

■質問

富士山の標高を教えて

結果は、全く関係ないはずの「メニュー考案」を選択しました。

どのような質問が来ても、いずれかのツールが選択されるのかもしれません。

このことを考慮して、用意するツールを検討する必要がありそうです。

対応するツールが存在しない場合の検証

5. まとめ

今回は、エージェントノードを使って、Function Callingを使ってみました。

エージェンティック戦略が増えれば、Difyの活用方法が一気に広がりそうですね!

引き続き、Difyのアップデートを追っていこうと思います。

Acroquest Technologyでは、キャリア採用を行っています。
  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。 www.wantedly.com

GraphRAG Toolkit を使って Amazon Bedrock で GraphRAG を構築する

こんにちは、機械学習チーム YAMALEX の駿です。
YAMALEX は Acroquest 社内で発足した、会社の未来の技術を創る、機械学習がメインテーマのデータサイエンスチームです。
(詳細はリンク先をご覧ください。)

今回は AWS が提供するオープンソースツール GraphRAG Toolkit を使って、 GraphRAG に入門しようと思います。

GraphRAG Toolkit を使うと、 Amazon NeptuneAmazon OpenSearch Serverless を使用した GraphRAG システムをローコードで実装できます。

なお、2024年12月から Bedrock Knowledge Base で使用できるようになった GraphRAG とは別物なので、混同しないようご注意ください。

1. はじめに

1.1. GraphRAG とは

従来の RAG は、キーワード検索やベクトル検索を用いて関連情報を取得するのに対し、GraphRAG はナレッジグラフを利用して、検索結果の文脈をより深く理解し、関連性の高い情報を抽出する手法です。

従来の RAG ではキーワード検索やベクトル検索でヒットした情報しか回答生成に使用することができませんが、 GraphRAG ではキーワード検索やベクトル検索で得られた結果を起点にグラフを走査することで、検索にヒットしなかったが文脈的に関連のある情報も取得し、回答生成に活用できます。

すなわち、 GraphRAG は構造化されたエンティティ間の関係を利用して、より精度の高い情報検索と文脈理解を実現します。


GraphRAGの利点

1.2. GraphRAG Toolkit とは

GraphRAG Toolkit は AWS が提供するオープンソースの GraphRAG 用ライブラリで、 GraphRAG を使ったシステムの構築を簡易化する機能が多く提供されています。

github.com

Amazon Neptune Database をグラフ DB として、 Amazon OpenSearch Serverless をベクトル DB として使用可能です。

このツールキットを使用することで、非構造化データからエンティティとそのリレーションを抽出し、ナレッジグラフとして保存、ユーザーの質問に対してこのナレッジグラフをクエリすることで、より関連性の高い情報を提供するアプリケーションを構築できます。

今回は GraphRAG を試すためにこのツールキットを使用します。

GraphRAG Toolkit におけるナレッジグラフの基本構造

ナレッジグラフは、データをエンティティ(実体)とそのリレーション(関係性)として構造化し、意味的なつながりを表現するデータモデルです。

「エンティティ」と「リレーション」のネットワークとして情報を整理することで、関係性を考慮した検索や論理的な推論が可能です。

GraphRAG Toolkit 内では下記の用語と構成でナレッジグラフを構築します。

上にあるものほど、大きな抽象的な概念で、下に行くにつれて具体的になっていきます。

No 項目 概要
1 ドキュメント(Source) 元ドキュメントを表す属性 https://docs.aws.amazon.com/neptune/latest/userguide/intro.html
2 チャンク(Chunk) ドキュメントを小さい単位に分割したもの [](https://docs.aws.amazon.com/pdfs/neptune/latest/userguide/neptune-ug.pdf#intro) Amazon Neptune is a fast, reliable, fully managed graph database service that makes it easy to build and run applications that work with highly connected datasets. The core of Neptune is...
3 トピック(Topic) チャンクに記載されている主題 Amazon Neptune
4 文言(Statement) チャンクに書かれている文章や文言 The core of Neptune is a purpose-built, high-performance graph database engine.
5 事実(Fact) 文言から導かれる事実 Amazon Neptune HAS high-performance
6 エンティティ 事実の主語・目的語。実世界の「モノ」や「概念」にあたる Amazon Neptune

ナレッジグラフのイメージ(https://github.com/awslabs/graphrag-toolkit/blob/main/images/lexical-graph.png

1.3. Amazon Neptune とは

Amazon Neptune は、 AWS が提供するフルマネージド型のグラフデータベースサービスであり、データ間の関係性を効率的に管理・操作できます。

aws.amazon.com

Neptune は複数のグラフモデルをサポートし、柔軟なデータ操作が可能です。

ナレッジグラフの構築だけでなく、ソーシャルネットワーク分析、レコメンデーションシステムなど、多様なユースケースで活用されています。

使わない時間帯に「停止」したり、開発環境では T3 インスタンスなど比較的安価なインスタンスを使ったりして、コストを抑えられるのも、うれしいポイントです。

aws.amazon.com

2. 環境を構築する

今回構築する環境は GraphRAG Toolkit が用意している Cloudformation テンプレートで立ち上げます。

構成図

No 項目 概要
1 Amazon Neptune ナレッジグラフを保持し、検索する
2 Amazon OpenSearch Service グラフ検索と併せて使用するベクトル検索用
3 Amazon Bedrock チャンクからトピック、文言、事実、エンティティを抽出する。ベクトル DB に投入するベクトルを生成する
 抽出用モデル:Claude-3-Sonnet
 ベクトル化モデル:Titan Text Embedding V2
4 Notebook GraphRAG Toolkit を操作し、ドキュメントの投入と検索を行う

3. データを取り込む

上記 Cloudformation テンプレートを使用して環境を構築すると、サンプルノートブックがいくつか用意されています。

データの取り込みには 01-Combined-Extract-and-Build.ipynb (ドキュメントからのエンティティなどの抽出とグラフの構築をまとめて行う)、 02-Separate-Extract-and-Build.ipynb (エンティティなどの抽出とグラフの構築を別々に行う)のいずれかが使用できます。

ドキュメントの取り込みは下の手順で行われます。

  1. ドキュメントを細かい単位に分割する(チャンキング)
  2. チャンクをLLMに渡して、命題(proposition)を抽出する

    命題は、ナレッジグラフを作成するときに必要な6つの要素を抽出するための前処理として生成されるもので、 元のドキュメントに対して、複雑な文章は単純でわかりやすい文章に分割する、代名詞や略語を開く、といったクレンジングが行われています。

  3. 命題を LLM に渡して、トピック、文言、事実、エンティティを抽出する

  4. 抽出されたエンティティなどからナレッジグラフを構築し、グラフ DB に取り込む
  5. 文言を LLM に渡してエンベディングを行い、ベクトル DB に取り込む

GraphRAG Toolkit を使用すると、 extract メソッドを呼ぶだけで、上記手順をひとまとめに実施してくれるため、とても簡単に始めることができます。

3.1. 取り込まれるデータを確認する

今回は、 02-Separate-Extract-and-Build.ipynb を使用して、抽出用モデルが元のドキュメントをどのように処理してグラフ DB に取り込める形にしているのかを確認してみます。

ノートブック中の Extract フェーズを実施すると、 LLM がドキュメントを解釈し、エンティティ、属性の抽出、そしてそれぞれのリレーションを抽出します。
抽出結果は extracted/ ディレクトリに保存されます。

設定を変更することで S3 に保存することも可能なため、一度処理したものをS3に貯めておき、新しいデータが増えナレッジグラフを構築しなおす際や、別 DB に同じナレッジグラフを構築したくなった時などに、複数回抽出作業をする必要がなくなり、 LLM の制限やお財布にやさしくすることができます。

実際に extracted/ に出力された JSON の中身は下記のようになっています。(スペースの都合上、大幅に省略しています)

上で説明した、命題、トピック、文章、事実、エンティティがそれぞれ入れ子になって保存されていることが分かります。

{
  "id_": "aws:xxxx",
  "metadata": {
    "url": "https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html",
    "aws::graph::propositions": [
      // 命題
      "Neptune Analytics is a memory-optimized graph database engine for analytics",
      "Neptune Analytics allows getting insights and finding trends by processing large amounts of graph data in seconds"
    ],
    "aws::graph::topics": {
      "topics": [
        {
          // トピック
          "value": "Neptune Analytics",
          "entities": [
            {
              // エンティティ
              "value": "Neptune Analytics",
              "classification": "Software"
            }
          ],
          "statements": [
            {
              // 文言
              "value": "Neptune Analytics is a memory-optimized graph database engine for analytics",
              "facts": [
                // 事実
                {
                  "subject": {
                    "value": "Neptune Analytics",
                    "classification": "Software"
                  },
                  "predicate": {
                    "value": "OPTIMIZED FOR"
                  },
                  "complement": "memory"
                }
              ]
            }
          ]
        }
      ]
    }
  }
}

なお、日本語のドキュメントに対しても、良い感じに抽出してくれました。

{
  "id_": "aws:xxxx",
  "metadata": {
    "aws::graph::propositions": [
      // 命題
      "知識表現の方法",
      "ナレッジグラフはデータをエンティティと関係性のネットワークとして表現する",
      "ナレッジグラフは情報の意味を捉えやすくする強力な手法である"
    ],
    "aws::graph::topics": {
      "topics": [
        {
          // トピック
          "value": "Knowledge Representation",
          "entities": [
            {
              // エンティティ
              "value": "ナレッジグラフ",
              "classification": "Concept"
            }
          ],
          "statements": [
            {
              // 文言
              "value": "ナレッジグラフはデータをエンティティと関係性のネットワークとして表現する",
              "facts": [
                // 事実
                {
                  "subject": {
                    "value": "ナレッジグラフ",
                    "classification": "Concept"
                  },
                  "predicate": {
                    "value": "REPRESENTS"
                  },
                  "object": {
                    "value": "データ",
                    "classification": "Concept"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  }
}

3.2. 取り込まれたデータを確認する

CloudFormation で Notebook をデプロイした際、同時にグラフエクスプローラーがデプロイされています。
このグラフエクスプローラーを開くことで、構築されたナレッジグラフを実際に確認できます。

docs.aws.amazon.com

グラフエクスプローラーの開き方

下の図はAmazon NeptuneのドキュメントをGraphRAG Toolkit を使って取り込んで作成されたナレッジグラフの一部を表示したものです。

上に書いたように、ドキュメント、チャンク、トピック、文言、事実、エンティティの階層に分かれて、それぞれのリレーションが記載されていることが分かります。


実際に構築されたナレッジグラフの一部

4. 検索する

GraphRAG では、ベクトル検索で起点となるノードを検索し、その後ナレッジグラフを走査して最終的な検索結果を返却します。

GraphRAG Toolkit は大きく2つの検索方法を提供しています。

No 検索方法 利点 欠点 用途
1 TraversalBasedRetriever ・処理が軽量
・結果の再現性が高い
・未知の単語や固有名詞に強い
・柔軟性が低い
・検索精度が低め
カテゴリごとに整理された FAQ など
2 SemanticGuidedRetriever ・質問の意図に沿った情報を探索できる
・複雑な関連性を考慮できる
・検索結果の多様性を確保できる
・計算コストが高く、処理が重い 質問の意図に合った情報、多様性のある情報など柔軟で高度な情報検索が必要な場合

4.1. TraversalBasedRetriever

TraversalBasedRetriever はグラフ構造を順番に走査することで、情報を拡張する検索方法です。

決まった順番にナレッジグラフを走査するため、処理が軽量です。

TraversalBasedRetriever にも2つの手法があり、どちらか片方、もしくは両方を組み合わせて使用することが可能です。
デフォルト設定では両方を組み合わせた結果を返却します。

  1. EntityBasedSearch

    クエリ文字列からキーワードを抽出し、マッチするエンティティをグラフから探します(Bottom up)。
    マッチするエンティティを見つけたら、そこから事実、命題、トピックと大きい概念に向かって走査することで、検索を行います。
    未知語や固有名詞であっても、事前に整理されたナレッジグラフに従って、関連した情報を集められるのが特徴です。

    エンティティから出発するため、そのエンティティに関わる情報を幅広く取得できる傾向にあります。

  2. ChunkBasedSearch

    チャンクに対してクエリとのベクトル類似度を使いて検索を行います(Top down)。
    ヒットしたチャンクから、トピック、命題、事実と小さい概念に向かって走査することで、検索を行います。

    クエリに意味的に近いところから出発するため、より関連度の高い情報に絞って取得できる傾向にあります。

4.2. SemanticGuidedRetriever

SemanticGuidedRetriever は文言(Statement)をベクトル化したものに対して検索を行います。
ベクトル検索で取得した文言からビームサーチとパス解析を用いて、近隣のノードから探索して関連度の高いものを取得します。

また、リランクで質問の意図に沿った検索結果に絞る、多様性フィルターで類似した情報ばかりではなく多様性のある回答になるようにするなど、回答生成に必要な情報を検索するための仕組みが使われています。

ベクトル検索とグラフ検索のハイブリッドを行うことで、関連度を高く保ちつつ、幅広い検索結果を返すことができますが、その分処理が重くなります。

4.3. 検索結果を確認する

GraphRAG Toolkit に含まれる 04-Querying.ipynb を使って上の2つの検索方法を試すことができます。

各Retrieverに「Neptune Database と Neptune Analytics の違いは何ですか?」と聞いた場合の LLM の回答と回答に使用したドキュメントを確認しました。

4.3.1. TraversalBaseRetriever

Neptune DatabaseとNeptune Analyticsは補完的な関係にあります。

Neptune Databaseは、管理型のグラフデータベースサービスです。
データの永続的な保存、バックアップ、レプリケーションなどの機能を提供します。
[https://docs.aws.amazon.com/neptune/latest/userguide/intro.html]

一方、Neptune Analyticsは大規模なグラフデータを高速に分析するためのインメモリエンジンです。
Neptune DatabaseやS3からグラフデータを読み込み、事前構築されたグラフアルゴリズムや
カスタムクエリを実行して分析を行います。
[https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html]

つまり、Neptune Databaseはグラフデータの永続的な保存と管理を担い、
Neptune Analyticsはそのデータに対する高速な分析処理を可能にするサービスです。
データの保存と分析を分離することで、それぞれの機能に特化したパフォーマンスが得られます。
[https://docs.aws.amazon.com/neptune-analytics/latest/userguide/neptune-analytics-features.html]

■ドキュメント

[
  {
    "source": "https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html",
    "topic": "Neptune Analytics",
    "statements": [
      "Neptune Analytics can load data from a Neptune Database graph",
      "Neptune Analytics complements Amazon Neptune Database, a popular managed graph database",
      "Neptune Analytics can load data from a Neptune Database snapshot",
      "The Neptune Analytics vs Neptune Database page explains when to use Neptune Analytics and when to use Neptune Database",
      "Neptune Analytics can load graph data stored in Amazon S3"
    ]
  },
  {
    "source": "https://docs.aws.amazon.com/neptune/latest/userguide/intro.html",
    "topic": "Amazon Neptune",
    "statements": [
      "Neptune Analytics is an analytics database engine.",
      "Neptune Analytics complements Neptune database.",
      "The Neptune database has continuous backup to Amazon S3",
      "Amazon Neptune automatically detects database crashes and restarts",
      "Amazon Neptune increases database performance and availability"
    ]
  }
]

4.3.1. SemanticGuidedRetriever

Neptune DatabaseとNeptune Analyticsは異なる製品で、以下のような違いがあります。

Neptune Databaseはマネージド型のグラフデータベースサービスです。
データの永続的な保存と、低レイテンシーのクエリ実行を行うことができます。
[https://docs.aws.amazon.com/neptune/latest/userguide/intro.html]

一方、Neptune Analyticsはメモリ上でグラフデータを分析するためのエンジンです。
大規模なグラフデータセットをメモリに読み込み、事前に用意された高度な分析アルゴリズムや
独自のCypherクエリを高速に実行できます。
[https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html] 
Neptune Analyticsは、データ分析やデータサイエンス、探索的なワークロードに適しています。

つまり、Neptune Databaseはデータの永続的な保存と低レイテンシーのクエリ実行を、
Neptune Analyticsはメモリ上での大規模グラフデータの高速分析を主な目的としています。
Neptune Analyticsは、Neptune Databaseからデータを読み込んで分析することもできます。
[https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html]

■ドキュメント

<sources>
  <source_1>
    <source_1_metadata>
      <url>
        https://docs.aws.amazon.com/neptune-analytics/latest/userguide/what-is-neptune-analytics.html</url>
    </source_1_metadata>
    <statement_1.1>Neptune Analytics is a memory-optimized graph database engine for analytics</statement_1.1>
    <statement_1.2>Neptune Analytics is a memory-optimized graph database engine for analytics</statement_1.2>
    <statement_1.3>Neptune Analytics can load data from a Neptune Database graph</statement_1.3>
    <statement_1.4>Neptune Analytics can load data from a Neptune Database snapshot</statement_1.4>
    <statement_1.5>Neptune Analytics is an ideal choice for data-science workloads that require fast
      iteration for data, analytical and algorithmic processing, or vector search on graph data</statement_1.5>
  </source_1>
  <source_2>
    <source_2_metadata>
      <url>https://docs.aws.amazon.com/neptune/latest/userguide/intro.html</url>
    </source_2_metadata>
    <statement_2.1>Neptune Analytics is an analytics database engine.</statement_2.1>
    <statement_2.2>Neptune Analytics is a solution for quickly analyzing existing graph databases.</statement_2.2>
    <statement_2.3>Neptune Analytics is a solution for quickly analyzing graph datasets stored in a
      data lake.</statement_2.3>
    <statement_2.4>Amazon Neptune is a fully managed graph database service</statement_2.4>
    <statement_2.5>Amazon Neptune is a fully managed graph database service</statement_2.5>
  </source_2>
</sources>

なんとなく、 SemanticGuidedRetriever を使った場合の方が正しい回答をしてくれているように見えますが、各検索方法での検索精度の違いなどは今後の検証課題としたいと思います。

なお、 Traversal...Semantic... でレスポンスに含まれるドキュメントの型が異なりますが、これは今後のアップデートで統一してくれるとのことです。

まとめ

GraphRAG Toolkit を使って、 GraphRAG がどのようにデータを処理しているのかを見てきました。
実際に動かしてみながら中身を確認することで、 GraphRAG の特性を理解できたと思います。

そして、 GraphRAG Toolkit を使って、とても簡単に GraphRAG システムを構築できることが分かりました。
グラフ DB に入れるまでの面倒な処理をラップしてくれているのがありがたいですね。

Acroquest Technologyでは、キャリア採用を行っています。
  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。 www.wantedly.com

Amazon Bedrock Knowledge Bases のベクトルDBに Aurora Serverless v2 を利用する

こんにちは。大塚です。

今回は、Amazon Bedrock Knowledge Basesを使い、ベクトルDBとしてAmazon Aurora PostgreSQLの利用を試したいと思います。
昨年の12月にはBedrock Knowledge BasesのベクトルDBとしてAurora PostgreSQLをクイック作成できるようになり、セットアップ手順が大幅に簡素化されました。
このクイック作成機能も活用してセットアップをしてみます。

aws.amazon.com

1. ベクトルストアとして Aurora PostgreSQL をセットアップする

事前準備

今回はRAG用の外部データソースとしてS3を利用します。
後ほど、LLMの回答にS3に置かれた資料が参照されているかを確認します。

Knowledge Basesの作成

AWSマネジメントコンソール上で、Bedrockのページへ行き、GUI操作だけで簡単にKnowledge Basesを作成できます。

「Knowledge Base with vector store」をクリックすると、Knowledge Bases作成画面に遷移します。

「ステップ2 データソースを設定」では、事前準備で作成したS3のURIを指定します。
そして「ステップ3 埋め込みモデルを選択し、ベクトルDBを設定する」が本題です。
ベクトルDBの選択肢に「Amazon Aurora PostgresSQL Serverless」という新しい項目が増えているのでこちらを選択しましょう!
※ベクトルDBの選択肢はリージョンによって異なりますが、この記事では東京リージョンで試しています。

あとは「次へ」を押下し作成内容を確認して完了です。
GUI操作だけで済むので直感的で簡単ですね!

RDSのコンソールから作成されたデータベースを確認できます。

DBテーブルは下記のように作成されていました。

Bedrock_Knowledge_Base_Cluster=> \d bedrock_knowledge_base
        Table "bedrock_integration.bedrock_knowledge_base"
  Column   |        Type         | Collation | Nullable | Default
-----------+---------------------+-----------+----------+---------
 id        | uuid                |           | not null |
 embedding | public.vector(1536) |           |          |
 chunks    | text                |           |          |
 metadata  | jsonb               |           |          |
Indexes:
    "bedrock_knowledge_base_pkey" PRIMARY KEY, btree (id)
    "bedrock_knowledge_base_embedding_idx" hnsw (embedding public.vector_l2_ops)

Knowledge Basesのテスト

作成したKnowledge Basesを選択すると「ナレッジベースをテスト」という画面があります。
ここでLLMに質問をして想定した回答が返ってくるかテストします。
今回は「アジャイル開発のメリットはなんですか?」という質問をしてみました。
想定通りに事前準備でS3に配置しておいた資料を参照した回答が返ってきたのでうまく動いていそうです。


2. OpenSearch Severless と比較する

ベクトルDBとして利用される代表サービスとしてOpenSearch Serverlessがあります。
ここでAurora Severless v2を利用する場合との差分を整理しておきます。

機能

ベクトルDBとしてAurora PostgreSQLを利用する場合、検索タイプはセマンティック検索のみサポートされています。

一方、OpenSearch Serverlessを利用する場合は、ハイブリッド検索とセマンティック検索を選択できます。

  • セマンティック検索: 単なるキーワード一致ではなく意味的に関連する情報を検索する
  • ハイブリッド検索: キーワードによる検索とセマンティック検索を組み合わせて検索する

検索の機能性としては、OpenSearch Serverlessの方がすぐれていますね。
キーワードによる検索も組み込みたい場合はOpenSearch Severlessを選択しましょう。

コスト

OpenSearch Serverlessのコンピューティング料金は、利用していないときでも時間単位の課金が発生します。
米国東部(バージニア北部)だと1ユニットあたり0.24USD/hです。
ドキュメントによると少なくとも2ユニットについて課金されると記載されているので、0.24USD/h * 720h * 2 = 345USD/月程度かかります。

一方でAurora Severless v2では、0.12USDと安価で、0ユニットへのスケーリングにも対応しています。
そのため、利用していないときのコストを抑えることができます。

aws.amazon.com

先ほどクイック作成したAurora PostgreSQLインスタンス設定を確認すると、想定通り0ユニットへのスケーリングに対応していました。

CloudWatchでユニット使用率(ACU)を見ると、利用していないときに0ユニットへスケーリングされていることを確認できました。

3. 検索速度を確認する

最後に、ドキュメント数を増やした場合の検索速度やACUを確認してみます。
データソースには、BBC News Summary | Kaggleを使用し、約9,000件のデータをS3に配置しました。

「1. Bedrock Knowledge BasesのベクトルDBとしてAurora PostgreSQLをセットアップする」と同様にLLMへ質問してみました。
結果はドキュメント数が少なかったときと同様に数十ミリ秒で回答が返ってきました。
今回利用したデータセット程度であれば検索速度も特に問題なさそうです。

ACUを確認するとドキュメント投入時のACUが30%程度(16(最大スケール時のユニット数) * 0.3 = 5ユニット)、LLMによる回答生成時のACUが15%程度(16 * 0.15 = 2.5ユニット)でした。

ベクトルDBのReadLatencyは0.01秒に収まっていたのでストレスなく使えそうです。

4. まとめ

今回は、Bedrock Knowledge BasesでベクトルDBにAurora Serverless v2の利用を試しました。
クイック作成機能もあり、数クリックのGUI操作だけで簡単にベクトルDBを用意できました。
利用していないときのコストを抑えたいという要求も手間なく実現できそうです。

最後に

Bedrock Knowledge Basesを削除するだけでは、ベクトルDBなどのクイック作成した他のリソースは削除されません。
不要であれば手動で削除することを忘れないようにしましょう。

Acroquest Technologyでは、キャリア採用を行っています。

  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。

www.wantedly.com

時系列基盤モデルChronos-Boltでお手軽に時系列予測を試してみた

皆さんこんにちは
Acroquestのデータサイエンスチーム「YAMALEX」のチームリーダ、@tereka114です。
YAMALEXチームでは、コンペティションへの参加や自社製品開発、技術研究などに日々取り組んでいます。
(詳細はこちらをご覧ください。)

LLMやVLMをはじめとした基盤モデルが近年、多く公開されています。
画像や自然言語処理といったものとは異なりますが、時系列モデリングでも基盤モデルが利用されようとしています。

本記事では、時系列基盤モデルの一つである「Chronos-Bolt」を紹介します。

Chronos-Boltについて

Chronosは端的に言えば、予め様々な時系列を学習させることで、適用するデータの学習をしなくとも、時系列予測を可能とする時系列基盤モデルです。
そのChronosの後継モデルがChronos-Boltになり、Chronosと比較して、精度、性能共に大きく向上しました。

参考1)Chronosの論文
arxiv.org

本記事ではAutoGluonを利用して、Chronos-Boltでの時系列予測処理を実装してみました。
AutoGluonは、AWSが中心となって開発されているOSSのAutoMLフレームワークです。AutoGluonには、いくつかの時系列予測モデルが実装されており、Chronos-Boltも含まれています。

参考2)追加学習なしの zero-shot で高精度な時系列予測 : Chronos-Bolt を AutoGluon で利用する(AWS公式ブログ)
aws.amazon.com

1. 学習不要で高精度な推論ができる。
Chronos/Chronos-Boltでは、学習なしで時系列予測を可能とするために、既存の様々な時系列データに加え、TS-MixupやKernelSynthといった合成データを作成する手法も利用し、多くの時系列データを学習しています。
それにより、ドメインに対する学習がない場合でも精度をある程度担保した予測ができます。
一般的に、予測精度を高めるためには学習が必要ですが、Chronos-Boltは学習データが存在しないケースにおいても一定の精度を見込むことができます。

2. Chronosモデルと比較して高速(最大260倍)
Chronosモデルでは一度に1つのステップの未来を予測しています。
しかし、Chronos-Boltは複数の予測(t, t+1, t+2)を同時に推論することで高速化を実現しています。公式ブログのベンチマークによれば、Chronosと同じモデルの大きさで、最大260倍の性能を発揮しています。

Chronos-Boltの推論速度(AWS公式ブログより)

3. Chronosモデルと比較して高精度
公式のベンチマークによれば、Chronosモデルと比較して高精度の結果が得られています。
この点においてもChronos-Boltを利用するメリットがあります。

Chronos-Boltを用いた精度比較(AWS公式ブログより)

Chronos-Boltを使った時系列予測

本記事ではChronos-Boltを利用した次の3つのパタンを紹介します。

パタン 説明
ゼロショット推論 学習なしで推論する
Finetune実施 学習ありで推論する
回帰モデルを利用した特徴量の外挿利用 推論する時系列以外にも補助的に利用する特徴量を使う。

準備

必要なライブラリのインストール

Chronos-Boltを利用するためには、事前にautogluonをインストールする必要があります。

pip install autogluon
データ準備

データセットはKaggleで公開されている「Store Sales - Time Series Forecasting」を利用します。
エクアドルに存在するリテール「Corporación Favorita」の商品売上数のデータを利用します。
www.kaggle.com

そのままのデータ形式では、適用が難しいので、次の実装で加工します。

import polars as pl

transaction = pl.read_csv("./data/store-sales-time-series-forecasting/transactions.csv")
holiday = pl.read_csv("./data/store-sales-time-series-forecasting/holidays_events.csv")

transaction = transaction.join(holiday, how="left", on="date")
transaction = transaction.fill_null("null")
transaction = transaction.with_columns(
    pl.col("date").str.to_date()
)
transaction = transaction.with_columns(
    pl.col("date").dt.month().alias("month"),
    pl.col("date").dt.day().alias("day"),
    pl.col("date").dt.weekday().alias("weekday")
)

df = transaction
train_df = df.filter(
    pl.col("date").dt.year() < 2017
)
train_df.write_csv("./data/train.csv")
valid_df = df.filter(
    (pl.col("date").dt.year() >= 2017) & (pl.col("date").dt.month() == 1)
)
valid_df = pl.concat([train_df, valid_df], how="diagonal_relaxed")
valid_df.write_csv("./data/valid.csv")

本解析で利用する主要なパラメータを記載します。

項目 説明
date 日付
store_nbr 店舗
transactions 取引量★今回の予測値
type 祝日ORイベント
locale 適用エリア
locale_name 地域などの名前
month dateから抽出した月
day dateから抽出した日
weekday dateから抽出した曜日

ゼロショット推論

ゼロショットで推論するのは非常に簡単です。
次の実装で対応できます。

id_columnはグルーピングするカテゴリ、timestamp_columnは時間を示す列、また、targetで予測列を指定します。
TimeSeriesPredictor.fitメソッドにて、presets="bolt_base"を指定することで、Chronos-Boltを利用できます。この際、bolt_baseをbolt_small/bolt_tinyにすることで、Chronos-Boltの別サイズのモデルの利用ができます。

import polars as pl
from autogluon.timeseries import TimeSeriesDataFrame, TimeSeriesPredictor

train_data = TimeSeriesDataFrame.from_path( 
     "data/train.csv", 
     id_column="store_nbr", 
     timestamp_column="date", 
)
predictor = TimeSeriesPredictor(prediction_length=30, freq="D", target="transactions").fit(train_data, presets="bolt_base")
predictions = predictor.predict(train_data)

推論結果を可視化します。
autogluonに可視化用のutility関数がありますので、その関数を利用します。
一時的にデータが欠損している部分がありますが、学習なしでも概ね追従できていることがわかります。

test_data = TimeSeriesDataFrame.from_path( 
     "data/valid.csv", 
     id_column="store_nbr", 
     timestamp_column="date", 
)
predictor.plot(test_data,predictions,max_history_length=365,item_ids=[25])

本プロットの青線が実績、オレンジの線がChronos-Boltによる予測結果を示しています。
また、オレンジは線の前後で網掛けになっていますが、こちらは80%信頼区間が表現されています。

推論結果(ゼロショット)

Finetune

次にFinetuneして学習した結果を利用して、時系列予測を試みます。
Finetuneは次の実装で可能です。
この実装では、ゼロショットとFinetuneしたモデルの2パタンのモデルを作成されます。
hyperparametersに含まれるChronosキーの中にリストがあり、ゼロショットとFinetuneしたモデルの2パタンを定義しています。主なポイントとして、fine_tuneをTrueにすることです。

predictor = TimeSeriesPredictor(prediction_length=31, eval_metric="MASE", freq="D", target="transactions").fit( 
     train_data, 
     hyperparameters={ 
         "Chronos": [ 
             {"model_path": "bolt_base", "ag_args": {"name_suffix": "ZeroShot"}}, 
             {"model_path": "bolt_base", "fine_tune": True, "ag_args": {"name_suffix": "FineTuned"}}, 
         ] 
     }, 
     enable_ensemble=False, 
     time_limit=600, 
)

終了後に、次の実装でゼロショットとFinetuneしたモデルの評価結果を取得できます。

predictor.leaderboard(test_data)
学習結果(外挿あり)

また、本predictorの実装を利用した結果を次の通り予測、プロットすることが可能です。

predictions = predictor.predict(train_data, model="ChronosZeroShot[bolt_base]")
predictor.plot(test_data,predictions,max_history_length=365,item_ids=symbols, max_num_item_ids=len(symbols))

ゼロショットと比較して、より実績にフィットしているように見えます。

推論結果(Finetune

特徴量の外挿利用

予測対象となる時系列データ以外にも補助的に利用できる時系列が含まれる場合があります。
例えば、店舗の売上に対して、来店に影響する降水量といったものが関係する場合があり、そのような場合に利用ができます。
ただし、外挿は当日のデータを利用することになりますので、検証するうえで、当日のデータを獲得できない場合、当日の予測をすることは難しいです。
(例:予測前日に予測当日の正確な降水量を使う場合)

外挿を利用する場合の予測値は次の通りの式になります。
回帰予測値 = Chronos-Boltの予測値 + CatBoost(外挿回帰モデル)の予測値

主な変更点として、TimeSeriesPredictorのknown_covariates_namesに外挿する列を指定します。
今回のモデルでは日付特徴(month, day, weekday)、祝日情報(type, locale, locale_name)を入力します。実装は次の通りです。

predictor = TimeSeriesPredictor(
    prediction_length=31,
    eval_metric="MASE",
    target="transactions",
    known_covariates_names=["type", "locale", "locale_name", "month", "day", "weekday"],
    freq="D"
).fit(
    train_data,
    hyperparameters={
        "Chronos": [
            {"model_path": "bolt_base", "ag_args": {"name_suffix": "ZeroShot"}},
            {
                "model_path": "bolt_base",
                "covariate_regressor": "CAT",
                "target_scaler": "standard",
                "ag_args": {"name_suffix": "WithRegressor"},
            },
        ],
    },
    time_limit=600,
    enable_ensemble=False,
)

Finetuneと同じように比較が可能です。

predictor.leaderboard(test_data)
学習結果(外挿)

今回の予測では、外挿となる特徴量を与えることが必要です。
こちらの推論は31日全てのデータが揃っているものでなければ、難しいので、全て揃っているstore_nbrが25のデータにフィルタリングして推論結果を可視化します。
実装は次の通りです。

filtered_id_df = train_data.to_data_frame().loc[25]
filtered_id_df['item_id'] = 25
filtered_id_df['timestamp'] = filtered_id_df.index
train_data = TimeSeriesDataFrame.from_data_frame(filtered_id_df)

filtered_id_df = test_data.to_data_frame().loc[25]
filtered_id_df['item_id'] = 25
filtered_id_df['timestamp'] = filtered_id_df.index
test_data = TimeSeriesDataFrame.from_data_frame(filtered_id_df)

predictions = predictor.predict(train_data, model="ChronosWithRegressor[bolt_base]", 
                                known_covariates =test_data
                               )
predictor.plot(test_data,predictions,max_history_length=365,
               item_ids=[25], max_num_item_ids=1)

更にFinetuneと比較して実績線に近くなったように見えます。

推論結果(外挿)

最後に

Auto GluonからChronos-Boltを簡単に利用し、時系列予測を試せました。
LLMのような基盤モデルの考えが、時系列モデルにも応用ができるのは非常に面白く、今後の発展も期待できそうです。

Acroquest Technologyでは、キャリア採用を行っています。

  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。

www.wantedly.com

Amazon Bedrock Flows で対話的なフローを行ってみる

はじめに

こんにちは一史です。
冬にもかかわらず、自宅のモンステラが新芽を出しており、生命力に驚いています。

さて最近、Amazon Bedrock Flowsの新機能としてマルチターン形式の会話機能がサポートされました。
aws.amazon.com

従来は、ユーザーが1回のプロンプトで処理に必要な情報を全て入力する必要がありましたが、マルチターン形式の会話により不足している情報を適宜AIが聞き返すことが簡単に実現できます。
今回はこのマルチターン形式の会話機能により、対話的なフローを行ってみます。

概要

Amazon Bedrock Flowsとは?

Amazon Bedrock Flowsは、AWSが提供するGUIベースの生成AIフレームワークです。
これを利用すると、独自のAIエージェントやチャットボットを簡単に構築することができます。
詳細な説明については以下記事で紹介していますので、参考にしていただければと思います。
acro-engineer.hatenablog.com

マルチターンの会話機能とは?

今回新たにサポートされたマルチターンの会話機能は、不足している情報をユーザーに聞き返す、対話形式のフローを可能にするものです。

例えば、旅行プランの提案・予約フローがあった場合、単一ターンの会話と、マルチターンの会話では以下のような違いになります。

単一ターンとマルチターンの会話例の比較

従来の単一ターンの会話では、入力された文章から、必要情報を取り出して処理をする場合、対象文章に必要情報が全て含まれている必要がありました。
もし必要情報が入力に含まれていなかった場合は後続処理に移行してしまいます。
そのため、処理ができなくなるか、AIが推測して必要情報を作り出し意図しない挙動になる場合があります。

一方、マルチターンの会話機能を使うことで、不足情報があれば次の処理へは行かずに、ユーザーに聞き返すようになります。
このように、マルチターンの会話機能を使うことで、より自然な対話フローを簡単に実現できます。

Amazon Bedrock Flowsでマルチターンの会話をするフローを作成

それではAmazon Bedrock Flowsでマルチターンの会話機能を使用する方法を、紹介していきます。
今回は例として、予算・PCの用途・デスクトップかノートPCか、をもとにPCを推薦するフローを作成していきます。

フローの概要

まず今回作成するフローの全体像はこちらです。

PC推薦フロー


ユーザーからの入力はエージェントノードで受け取ります。
プロンプトノードもユーザーからの入力を、文章形式で受け取れますが、マルチターンの会話機能はエージェントのみの機能なためエージェントを用います。
そして、エージェントでは予算・PCの用途・デスクトップかノートPCかの情報を抽出し、後続のAWS Lambdaに渡してPCを推薦します。
Lambdaでの推薦は簡易的に、抽出した情報の組み合わせに対応するPC名を返すようにしています。

マルチターンの会話をするエージェントの作成

まず、ユーザー入力を受け取り、PC推薦に必要な情報を抽出するエージェントを作成します。
今回エージェントに渡した命令は以下です。

ユーザーの入力を分析し、以下の3つのパラメータを抽出してください。  

# 抽出すべき情報
1. 価格帯(price_range)  
   - ユーザーの予算が 15万円未満 の場合、"lower_than_150000yen" を返す  
   - ユーザーの予算が 15万円以上 の場合、"higher_than_150000yen" を返す  

2. 用途(use_case)  
   - ゲーム用のPCが必要な場合、"game" を返す  
   - 仕事、ドキュメント作成、メールなどのビジネス用途の場合、"business" を返す  

3. PCの種類(pc_type)  
   - デスクトップPCが必要な場合、"desktop" を返す  
   - ノートPCが必要な場合、"laptop" を返す 

# 出力フォーマット  
抽出すべき情報を取り出せたら、以下のJSON形式で結果を返してください。

```json
{
  "price_range": "lower_than_150000yen",
  "use_case": "game",
  "pc_type": "laptop"
}
```

次に、マルチターンの会話をするための設定として、「その他の設定」の「ユーザー入力」を「有効」にします。
これによってマルチターンの対話が可能になります。

エージェントのマルチターンの会話機能設定

PC推薦Lambdaの作成

次に、エージェントが作成したJSONを受け取り、推薦するPCを返すLambdaを作成します。
今回は簡易的に、関数の中にPCの一覧を定義しておきます。

# PC推薦マップ
PC_RECOMMENDATION_MAP = {
    "lower_than_150000yen.game.desktop": "ASUS ROG Strix G15",
    "lower_than_150000yen.game.laptop": "Dell G15 Ryzen Edition",
    "lower_than_150000yen.business.desktop": "HP Pavilion Desktop TP01",
    "lower_than_150000yen.business.laptop": "Lenovo ThinkPad E14",
    "higher_than_150000yen.game.desktop": "Alienware Aurora R15",
    "higher_than_150000yen.game.laptop": "Razer Blade 15 Advanced",
    "higher_than_150000yen.business.desktop": "Apple Mac Studio",
    "higher_than_150000yen.business.laptop": "Apple MacBook Pro 16-inch",
}

def lambda_handler(event, context):
    # 入力パラメータの取得
    input_str = event.get("node", {}).get("inputs", [])[0].get("value", "")

    # エージェントが出力した文字列からJSONを抽出しパースする
    match = re.search(r'\{.*?\}', input_str, re.DOTALL)
    json_str = match.group(0) if match else None
    pc_params = json.loads(json_str)

    # PCの推薦
    recommend_key = f"{pc_params['price_range']}.{pc_params['use_case']}.{pc_params['pc_type']}"
    recommended_pc = PC_RECOMMENDATION_MAP.get(recommend_key, "no_recommended_pc")

    if recommended_pc == "no_recommended_pc":
        response = "お勧めできるPCはありませんでした。"
    else:
        response = f"{recommended_pc} がお薦めです。"

    return response

マルチターンの対話を行ってみる

それでは、作成したフローと対話をしてみます。

曖昧な質問に対して、具体的な内容を聞き返すか

ユーザーの曖昧な質問に対して、具体的な内容を聞き返すかを見てみます。

まず、マルチターンの会話機能がOFFの場合の結果と、この時のエージェントが後続に渡した出力は以下です。
ここでは、「お手頃価格のPCが欲しい」と値段を曖昧に伝えてみます。

マルチターンの会話機能がOFFの場合の結果
ありがとうございます。仕事用のお手頃価格のPCをお探しですね。より適切なおすすめができるように、もう少し詳しくお聞きしたいことがあります。

デスクトップPCとノートPCのどちらをお考えでしょうか?それぞれ特徴が異なりますので、ご希望をお聞かせいただけると助かります。

これを見ると、マルチターンの会話機能がOFFでもエージェントは聞き返そうとしているようですが、その内容がユーザーにではなく後続の処理に渡ってしまいエラーしたようです。

一方、マルチターンの会話機能をONにした場合の結果は以下です。

マルチターンの会話機能をONの場合の結果


結果をみると、エージェントは次の処理へは進まず、ユーザーからの曖昧な質問に対して具体的な内容を聞き返していることがわかります。
また、Lambdaで定義した推薦するPCは以下表の通りで、期待通り「Lenovo ThinkPad E14」が推薦されています。

価格帯 用途 PCの種類 推薦PC
15万円未満 ゲーム デスクトップ ASUS ROG Strix G15
15万円未満 ゲーム ノートPC Dell G15 Ryzen Edition
15万円未満 ビジネス デスクトップ HP Pavilion Desktop TP01
15万円未満 ビジネス ノートPC Lenovo ThinkPad E14
15万円以上 ゲーム デスクトップ Alienware Aurora R15
15万円以上 ゲーム ノートPC Razer Blade 15 Advanced
15万円以上 ビジネス デスクトップ Apple Mac Studio
15万円以上 ビジネス ノートPC Apple MacBook Pro 16-inch

1度のやり取りだけではなく、複数回のやり取りを踏まえて回答できるか

では次に、会話の往復が何度も発生した場合でも、それまでの会話全てをもとに回答ができるかを見ていきます。

以下ではPCの情報を小出しにして渡してみました。

往復する会話の回答結果

これをみると情報が3回の会話に分割されてしまっていますが、最初のユーザーメッセージにあった「20万円いかないくらい」という情報も含めて、期待するPCが推薦できていることがわかります。

まとめ

Amazon Bedrock Flowsのマルチターンの会話機能により、ユーザーの入力があいまいな場合や、会話が複数回往復しても適切に必要な情報が抽出できることがわかりました。
自然な対話形式のAIサービスを簡単に作成することができるため、是非お試しください。



Acroquest Technologyでは、キャリア採用を行っています。

  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

 

少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。

www.wantedly.com