Files
dify-docs/plugin-dev-ja/9232-agent.mdx
2025-07-16 16:42:34 +08:00

438 lines
18 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
dimensions:
type:
primary: implementation
detail: high
level: intermediate
standard_title: Agent
language: ja
title: Agent
description: このドキュメントでは、DifyのAgent戦略プラグインの開発プロセスについて詳しく説明します。ManifestファイルへのAgent戦略フィールドの追加、Agentプロバイダーの定義、Agent戦略を実装するためのコアステップが含まれます。パラメータの取得、モデルの呼び出し、ツールの呼び出し、ログの生成と管理に関する完全なサンプルコードも詳細に解説しています。
---
Agent戦略は、標準の入力内容と出力形式を定義する拡張可能なテンプレートです。具体的なAgent戦略インターフェースの機能コードを開発することで、CoT思考の連鎖/ ToT思考の木/ GoT思考のグラフ/ BoT思考の骨格など、さまざまなAgent戦略を実現し、[Sementic Kernel](https://learn.microsoft.com/en-us/semantic-kernel/overview/) のような複雑な戦略を実装できます。
### Manifest内へのフィールド追加
プラグインにAgent戦略を追加するには、`manifest.yaml`ファイル内に`plugins.agent_strategies`フィールドを新たに追加し、Agentプロバイダーも定義する必要があります。サンプルコードは以下の通りです。
```yaml
version: 0.0.2
type: plugin
author: "langgenius"
name: "agent"
plugins:
agent_strategies:
- "provider/agent.yaml"
```
ここでは、`manifest`ファイル内の一部の無関係なフィールドは省略されています。Manifestの詳細な形式については、[マニフェストファイルによるプラグイン情報の定義](/plugin-dev-ja/0411-plugin-info-by-manifest)ドキュメントを参照してください。
### Agentプロバイダーの定義
次に、`agent.yaml`ファイルを新規作成し、基本的なAgentプロバイダー情報を入力する必要があります。
```yaml
identity:
author: langgenius
name: agent
label:
en_US: Agent
zh_Hans: Agent
pt_BR: Agent
description:
en_US: Agent
zh_Hans: Agent
pt_BR: Agent
icon: icon.svg
strategies:
- strategies/function_calling.yaml
```
主にいくつかの記述的な基本情報を含み、現在のプロバイダーがどの戦略を含むかを指定します。上記のサンプルコードでは、最も基本的な`function_calling.yaml`戦略ファイルのみが指定されています。
### Agent戦略の定義と実装
#### 定義
次に、Agent戦略を実現できるコードを定義する必要があります。`function_calling.yaml`ファイルを新規作成します:
```yaml
identity:
name: function_calling
author: Dify
label:
en_US: FunctionCalling
zh_Hans: FunctionCalling
pt_BR: FunctionCalling
description:
en_US: Function Calling is a basic strategy for agent, model will use the tools provided to perform the task.
zh_Hans: Function Callingは基本的なAgent戦略であり、モデルは提供されたツールを使用してタスクを実行します。
pt_BR: Function Calling is a basic strategy for agent, model will use the tools provided to perform the task.
parameters:
- name: model
type: model-selector
scope: tool-call&llm
required: true
label:
en_US: Model
zh_Hans: モデル
pt_BR: Model
- name: tools
type: array[tools]
required: true
label:
en_US: Tools list
zh_Hans: ツールリスト
pt_BR: Tools list
- name: query
type: string
required: true
label:
en_US: Query
zh_Hans: ユーザーの質問
pt_BR: Query
- name: max_iterations
type: number
required: false
default: 5
label:
en_US: Max Iterations
zh_Hans: 最大反復回数
pt_BR: Max Iterations
max: 50
min: 1
extra:
python:
source: strategies/function_calling.py
```
コード形式は[`Tool`標準形式](tool.md)に似ており、`model`、`tools`、`query`、`max_iterations`など合計4つのパラメータを定義し、最も基本的なAgent戦略の実装を容易にします。このコードの意味は、ユーザーがモデルと使用するツールを選択し、最大反復回数を設定し、最終的にqueryを渡してAgentの実行を開始できるようにすることです。
#### 機能実装コードの作成
**パラメータの取得**
上記で定義された4つのパラメータに基づき、`model`タイプのパラメータは`model-selector`であり、`tool`タイプのパラメータは特殊な`array[tools]`です。パラメータで取得された形式は、SDKに組み込まれている`AgentModelConfig`と`list[ToolEntity]`を使用して変換できます。
```python
from dify_plugin.interfaces.agent import AgentModelConfig, AgentStrategy, ToolEntity
class FunctionCallingParams(BaseModel):
query: str
model: AgentModelConfig
tools: list[ToolEntity] | None
maximum_iterations: int = 3
class FunctionCallingAgentStrategy(AgentStrategy):
def _invoke(self, parameters: dict[str, Any]) -> Generator[AgentInvokeMessage]:
"""
Run FunctionCall agent application
"""
fc_params = FunctionCallingParams(**parameters)
```
**モデルの呼び出し**
指定されたモデルの呼び出しは、Agentプラグインに不可欠な機能です。SDK内の`session.model.invoke()`関数を使用してモデルを呼び出します。`model`から必要な入力パラメータを取得できます。
`invoke model`のメソッドシグネチャのサンプルコード:
```python
def invoke(
self,
model_config: LLMModelConfig,
prompt_messages: list[PromptMessage],
tools: list[PromptMessageTool] | None = None,
stop: list[str] | None = None,
stream: bool = True,
) -> Generator[LLMResultChunk, None, None] | LLMResult:
```
モデル情報`model_config`、プロンプト情報`prompt_messages`、およびツール情報`tools`を渡す必要があります。
そのうち`prompt_messages`パラメータは以下のサンプルコードを参照して呼び出すことができますが、`tool_messages`は一定の変換が必要です。
`invoke model`の使用方法のサンプルコードを参照してください:
```python
from collections.abc import Generator
from typing import Any
from pydantic import BaseModel
from dify_plugin.entities.agent import AgentInvokeMessage
from dify_plugin.entities.model.llm import LLMModelConfig
from dify_plugin.entities.model.message import (
PromptMessageTool,
SystemPromptMessage,
UserPromptMessage,
)
from dify_plugin.entities.tool import ToolParameter
from dify_plugin.interfaces.agent import AgentModelConfig, AgentStrategy, ToolEntity
class FunctionCallingParams(BaseModel):
query: str
instruction: str | None
model: AgentModelConfig
tools: list[ToolEntity] | None
maximum_iterations: int = 3
class FunctionCallingAgentStrategy(AgentStrategy):
def _invoke(self, parameters: dict[str, Any]) -> Generator[AgentInvokeMessage]:
"""
Run FunctionCall agent application
"""
# init params
fc_params = FunctionCallingParams(**parameters)
query = fc_params.query
model = fc_params.model
stop = fc_params.model.completion_params.get("stop", []) if fc_params.model.completion_params else []
prompt_messages = [
SystemPromptMessage(content="あなたのシステムプロンプトメッセージ"),
UserPromptMessage(content=query),
]
tools = fc_params.tools
prompt_messages_tools = self._init_prompt_tools(tools)
# invoke llm
chunks = self.session.model.llm.invoke(
model_config=LLMModelConfig(**model.model_dump(mode="json")),
prompt_messages=prompt_messages,
stream=True,
stop=stop,
tools=prompt_messages_tools,
)
def _init_prompt_tools(self, tools: list[ToolEntity] | None) -> list[PromptMessageTool]:
"""
Init tools
"""
prompt_messages_tools = []
for tool in tools or []:
try:
prompt_tool = self._convert_tool_to_prompt_message_tool(tool)
except Exception:
# APIツールは削除された可能性があります
continue
# save prompt tool
prompt_messages_tools.append(prompt_tool)
return prompt_messages_tools
def _convert_tool_to_prompt_message_tool(self, tool: ToolEntity) -> PromptMessageTool:
"""
convert tool to prompt message tool
"""
message_tool = PromptMessageTool(
name=tool.identity.name,
description=tool.description.llm if tool.description else "",
parameters={
"type": "object",
"properties": {},
"required": [],
},
)
parameters = tool.parameters
for parameter in parameters:
if parameter.form != ToolParameter.ToolParameterForm.LLM:
continue
parameter_type = parameter.type
if parameter.type in {
ToolParameter.ToolParameterType.FILE,
ToolParameter.ToolParameterType.FILES,
}:
continue
enum = []
if parameter.type == ToolParameter.ToolParameterType.SELECT:
enum = [option.value for option in parameter.options] if parameter.options else []
message_tool.parameters["properties"][parameter.name] = {
"type": parameter_type,
"description": parameter.llm_description or "",
}
if len(enum) > 0:
message_tool.parameters["properties"][parameter.name]["enum"] = enum
if parameter.required:
message_tool.parameters["required"].append(parameter.name)
return message_tool
```
**ツールの呼び出し**
ツールの呼び出しもAgentプラグインに不可欠な機能です。`self.session.tool.invoke()`を使用して呼び出すことができます。`invoke tool`のメソッドシグネチャのサンプルコード:
```python
def invoke(
self,
provider_type: ToolProviderType,
provider: str,
tool_name: str,
parameters: dict[str, Any],
) -> Generator[ToolInvokeMessage, None, None]
```
必須パラメータは`provider_type`、`provider`、`tool_name`、`parameters`です。そのうち`tool_name`と`parameters`は、Function CallingではLLMによって生成されることがよくあります。`invoke tool`の使用例コード:
```python
from dify_plugin.entities.tool import ToolProviderType
class FunctionCallingAgentStrategy(AgentStrategy):
def _invoke(self, parameters: dict[str, Any]) -> Generator[AgentInvokeMessage]:
"""
Run FunctionCall agent application
"""
fc_params = FunctionCallingParams(**parameters)
# tool_call_name and tool_call_args parameter is obtained from the output of LLM
tool_instances = {tool.identity.name: tool for tool in fc_params.tools} if fc_params.tools else {}
tool_instance = tool_instances[tool_call_name]
tool_invoke_responses = self.session.tool.invoke(
provider_type=ToolProviderType.BUILT_IN,
provider=tool_instance.identity.provider,
tool_name=tool_instance.identity.name,
# デフォルト値を追加
parameters={**tool_instance.runtime_parameters, **tool_call_args},
)
```
`self.session.tool.invoke()`関数の出力はGeneratorであり、同様にストリーミング解析が必要であることを意味します。
解析方法については、以下の関数を参照してください:
```python
import json
from collections.abc import Generator
from typing import cast
from dify_plugin.entities.agent import AgentInvokeMessage
from dify_plugin.entities.tool import ToolInvokeMessage
def parse_invoke_response(tool_invoke_responses: Generator[AgentInvokeMessage]) -> str:
result = ""
for response in tool_invoke_responses:
if response.type == ToolInvokeMessage.MessageType.TEXT:
result += cast(ToolInvokeMessage.TextMessage, response.message).text
elif response.type == ToolInvokeMessage.MessageType.LINK:
result += (
f"結果リンク: {cast(ToolInvokeMessage.TextMessage, response.message).text}。"
+ " ユーザーに確認するよう伝えてください。"
)
elif response.type in {
ToolInvokeMessage.MessageType.IMAGE_LINK,
ToolInvokeMessage.MessageType.IMAGE,
}:
result += (
"画像は既に作成されユーザーに送信済みです。"
+ "作成する必要はありません。ユーザーに今すぐ確認するよう伝えてください。"
)
elif response.type == ToolInvokeMessage.MessageType.JSON:
text = json.dumps(cast(ToolInvokeMessage.JsonMessage, response.message).json_object, ensure_ascii=False)
result += f"ツール応答: {text}。"
else:
result += f"ツール応答: {response.message!r}。"
return result
```
#### Log
Agentの思考プロセスを確認したい場合、正常に返されたメッセージを確認する以外に、専用のインターフェースを使用してAgent全体の思考プロセスをツリー構造で表示することもできます。
**ログの作成**
* このインターフェースは`AgentLogMessage`を作成して返します。このMessageはログ内のツリーのードを表します。
* `parent`が渡された場合、そのノードは親ノードを持つことを示します。
* ステータスはデフォルトで"Success"(成功)です。ただし、タスクの実行プロセスをよりよく表示したい場合は、まずステータスを"start"に設定して「実行中」のログを表示し、タスク完了後にそのログのステータスを"Success"に更新することができます。これにより、ユーザーはタスクの開始から完了までの全プロセスを明確に確認できます。
* `label`は、最終的にユーザーにログのタイトルを表示するために使用されます。
```python
def create_log_message(
self,
label: str,
data: Mapping[str, Any],
status: AgentInvokeMessage.LogMessage.LogStatus = AgentInvokeMessage.LogMessage.LogStatus.SUCCESS,
parent: AgentInvokeMessage | None = None,
) -> AgentInvokeMessage
```
**ログの完了**
前のステップで開始ステータスとして`start`状態を選択した場合、ログ完了インターフェースを使用してステータスを変更できます。
```python
def finish_log_message(
self,
log: AgentInvokeMessage,
status: AgentInvokeMessage.LogMessage.LogStatus = AgentInvokeMessage.LogMessage.LogStatus.SUCCESS,
error: Optional[str] = None,
) -> AgentInvokeMessage
```
**インスタンス**
この例では、単純な2ステップの実行プロセスを示しています。まず「思考中」のステータスログを出力し、次に実際のタスク処理を完了します。
```python
class FunctionCallingAgentStrategy(AgentStrategy):
def _invoke(self, parameters: dict[str, Any]) -> Generator[AgentInvokeMessage]:
thinking_log = self.create_log_message(
data={
"Query": parameters.get("query"),
},
label="思考中",
status=AgentInvokeMessage.LogMessage.LogStatus.START,
)
yield thinking_log
llm_response = self.session.model.llm.invoke(
model_config=LLMModelConfig(
provider="openai",
model="gpt-4o-mini",
mode="chat",
completion_params={},
),
prompt_messages=[
SystemPromptMessage(content="あなたは役立つアシスタントです"),
UserPromptMessage(content=parameters.get("query")),
],
stream=False,
tools=[],
)
thinking_log = self.finish_log_message(
log=thinking_log,
)
yield thinking_log
yield self.create_text_message(text=llm_response.message.content)
```
## 関連リソース
- [プラグイン開発の基本概念](/plugin-dev-ja/0111-getting-started-dify-plugin) - プラグイン開発の全体的なアーキテクチャを理解する
- [Agent戦略プラグイン開発例](/plugin-dev-ja/9433-agent-strategy-plugin) - 実際のAgent戦略プラグイン開発例
- [マニフェストファイルによるプラグイン情報の定義](/plugin-dev-ja/0411-plugin-info-by-manifest) - Manifestファイルの詳細な形式を理解する
- [モデルの逆呼び出し](/plugin-dev-ja/9242-reverse-invocation-model) - プラットフォーム内のモデル機能を呼び出す方法を理解する
- [ツールの逆呼び出し](/plugin-dev-ja/9242-reverse-invocation-tool) - 他のプラグインを呼び出す方法を理解する
{/*
Contributing Section
DO NOT edit this section!
It will be automatically generated by the script.
*/}
---
[このページを編集する](https://github.com/langgenius/dify-docs/edit/main/plugin-dev-ja/9232-agent.mdx) | [問題を報告する](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml)