GraphAIを使用したRAG(Retrieval Augmented Generation)の実装例と出力結果を解説します。以下のコードが全体像です:
version: 0.5
nodes:
# 1. コンテンツの準備
source:
value: |
GraphAIは非同期データフロー実行エンジンです。
開発者がYAMLやJSONでエージェントワークフローを宣言的に記述することで、
エージェントアプリケーションを構築できます。
GraphAIには2種類のノードがあります。
計算ノードはエージェントに関連付けられ、特定の計算を実行します。
静的ノードは、コンピュータ言語の変数のように値のプレースホルダーです。
GraphAIは設計上、データフローグラフを非巡回にする必要がありますが、
ループ、ネスト、if/unless、マッピングなどの制御フローメカニズムが追加されています。
query:
value: GraphAIのノードの種類について教えてください。
# 2. テキストのチャンキング
chunks:
agent: stringSplitterAgent
inputs:
text: :source
params:
separator: "\n\n" # 段落で分割
# 3. 各チャンクのembedding取得
chunkEmbeddings:
agent: stringEmbeddingsAgent
inputs:
array: :chunks.contents
# 4. クエリのembedding取得
queryEmbedding:
agent: stringEmbeddingsAgent
inputs:
item: :query
# 5. 類似度計算
similarities:
agent: dotProductAgent
inputs:
matrix: :chunkEmbeddings
vector: :queryEmbedding.$0
# 6. 類似度でチャンクをソート
sortedChunks:
agent: sortByValuesAgent
inputs:
array: :chunks.contents
values: :similarities
# 7. コンテキストの準備
referenceText:
agent: tokenBoundStringsAgent
inputs:
chunks: :sortedChunks
params:
limit: 2000 # トークン数の制限
# 8. プロンプトの構築
prompt:
agent: stringTemplateAgent
inputs:
query: :query
context: :referenceText.content
params:
template: |-
以下の文書を参考に質問に答えてください:
${context}
質問:${query}
# 9. LLMでの回答生成
llmResponse:
agent: openAIAgent
inputs:
prompt: :prompt
params:
model: gpt-4o
console:
after: true
# 10. 結果の出力
output:
agent: copyAgent
inputs:
text: :llmResponse.text
console:
after: true
isResult: true
RAGの実装ステップ
1. 入力データの準備と分割
最初に、分析したい長文とユーザークエリを準備し、テキストを分割します:
source:
value: |
GraphAIは非同期データフロー実行エンジンです。
# ...(ソーステキスト)
query:
value: GraphAIのノードの種類について教えてください。
chunks:
agent: stringSplitterAgent
inputs:
text: :source
params:
separator: "\n\n" # 段落単位での分割
2. Embedding生成とベクトル検索
分割したテキストとクエリのembeddingを生成し、類似度を計算します:
chunkEmbeddings:
agent: stringEmbeddingsAgent
inputs:
array: :chunks.contents
queryEmbedding:
agent: stringEmbeddingsAgent
inputs:
item: :query
similarities:
agent: dotProductAgent
inputs:
matrix: :chunkEmbeddings
vector: :queryEmbedding.$0
sortedChunks:
agent: sortByValuesAgent
inputs:
array: :chunks.contents
values: :similarities
チャンクしたテキストとユーザーの入力をベクトル化して類似解析をし、並び替えをします。
3. コンテキストの最適化とプロンプト生成
関連性の高いチャンクを選択し、プロンプトを構築します:
referenceText:
agent: tokenBoundStringsAgent
inputs:
chunks: :sortedChunks
params:
limit: 2000 # トークン制限
prompt:
agent: stringTemplateAgent
inputs:
query: :query
context: :referenceText.content
params:
template: |-
以下の文書を参考に質問に答えてください:
${context}
質問:${query}
4. LLM処理と出力
最後に、GPT-4で回答を生成し、結果を出力します:
llmResponse:
agent: openAIAgent
inputs:
prompt: :prompt
params:
model: gpt-4o
console:
after: true
output:
agent: copyAgent
inputs:
text: :llmResponse.text
console:
after: true
isResult: true
実行結果
{
"id": "chatcmpl-Ae6Xsqv3WXPeYwd4OQKE2Telx925S",
"object": "chat.completion",
"created": 1734121644,
"model": "gpt-4o-2024-08-06",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "GraphAIには2種類のノードがあります。1つ目は「計算ノード」で、エージェントに関連付けられ特定の計算を実行します。2つ目は「静的ノード」で、コンピュータ言語の変数のように値のプレースホルダーとして機能します。",
"refusal": null
}
}
],
"usage": {
"prompt_tokens": 206,
"completion_tokens": 76,
"total_tokens": 282
}
}
実装の詳細分析
- チャンキングの特徴
chunks:
agent: stringSplitterAgent
inputs:
text: :source
params:
separator: "\n\n"
- 段落単位での分割により文脈を維持
- separatorパラメータによる柔軟な分割制御
- ベクトル検索の最適化
similarities:
agent: dotProductAgent
inputs:
matrix: :chunkEmbeddings
vector: :queryEmbedding.$0
- ドット積による効率的な類似度計算
- 行列演算による高速な処理
- コンテキスト管理
referenceText:
agent: tokenBoundStringsAgent
inputs:
chunks: :sortedChunks
params:
limit: 2000
- トークン制限による最適なコンテキストサイズの管理
- 関連性の高いチャンクの優先的な選択
まとめ
このGraphAIによるRAG実装の主な特徴は以下の点です:
- 段落単位でのチャンキングによる文脈の維持
- トークン制限による効率的なコンテキスト最適化
- 独立したノードによる明確な処理の分離
- 宣言的な記述による高い可読性と保守性
この実装は、大規模なドキュメント検索や質問応答システムなど、様々な実用的なアプリケーションに応用できます。また、各処理ステップが独立したノードとして定義されているため、システムの拡張や改善が容易です。