catch-img

【Dify活用】生成AIでSNS投稿を爆速で作成する方法②エージェントの活用

前回は①文字調整関数の使い方を紹介しました。当記事では②エージェント(Function Calling)の活用を解説します。

目次[非表示]

  1. Difyについて
  2. エージェントを使うべき理由
  3. 外部関数の利用 Function Calling
  4. Difyで自作APIを叩く方法
    1. ①コードファイルをサーバーにデプロイする
    2. ②APIサーバーを立てる
    3. ③Dify用のOPEN APIスキーマを作る
  5. エージェントで使う
    1. 戻り値には具体的な改善ポイントを入れる
  6. おすすめの組み込みツール
    1. current_time
    2. tavily_search
    3. jina_reader

Difyには外部関数をツールとして生成AIに使わせる機能「エージェント」が用意されています。

このエージェントに「SNS投稿文章の作成」と「文字数のチェック」をペアで実行させることが当記事の目的となります。

Difyについて

Difyは、オープンソースのLLM(大規模言語モデル)アプリケーション開発プラットフォームです。

Difyでは会話形式の「チャットボット」、フローチャート形式で処理を行う「ワークフロー」、そして外部ツールを実行させる「エージェント」と大きく3つの機能に分かれています。Difyの機能一覧

エージェントを使うべき理由

Difyを使うと「テキストジェネレーター」というメニューがあるので、SNSの文章やプレスリリース作成などはこちらを使いたくなると思います。

しかしテキストジェネレーターは、出力できるのは1回のみで、修正・改善する機能はありません。

テキスト原稿の作成などは「出力→評価→再修正」を繰り返すことが重要になります。

この作業が可能で、かつ外部関数(外部の機能)が使えるのが「エージェント」です。

※チャットフローも外部ツールを利用できますが、分岐が面倒で結果的に人為的になってしまうため、まずはシンプルなエージェントがおすすめです。

外部関数の利用 Function Calling

この外部関数を生成AIに使わせる機能のことをOpen AIでは「Function Calling」と読んでいます。

  https://platform.openai.com/docs/guides/function-calling https://platform.openai.com/docs/guides/function-calling

Function Callingは複雑な処理となり、例えばPython上の実装だけでも以下の分量のコードが必要となります。

# 文字数チェック関数
def check_tweet_len(text):
    response_message = ""
    parsed_tweet = parse_tweet(text)
    print(parsed_tweet)

    # ツイートが有効かどうかを判断
    if parsed_tweet.valid:
        response_message = "このテキストはTwitterに投稿可能です。"
    else:
        # 重み付けされた文字数が280文字を超えている場合
        if parsed_tweet.weightedLength > 280:
            response_message = f"テキストが長すぎます。{parsed_tweet.weightedLength}文字ありますが、280文字以下にしてください。"
        # permillageを使って、許容範囲を超えているかを詳細に確認
        elif parsed_tweet.permillage > 1000:
            response_message = f"テキストが許容される最大値を超えています。現在の使用量: {parsed_tweet.permillage / 10}%"
        # その他の無効な理由
        else:
            response_message = "テキストは何らかの理由で無効です。"

    # 有効範囲内でテキストを調整するための提案
    if not parsed_tweet.valid:
        response_message += f"有効なテキスト範囲: {parsed_tweet.validRangeStart}から{parsed_tweet.validRangeEnd}文字目までです。"

    return response_message

client = OpenAI(api_key = userdata.get('OPENAI_API_KEY'))
# toolの設定
tools = [
    {
        "type": "function",
        "function": {
            "name": "check_tweet_len",
            "description": "与えられたテキストがX(旧Twitter)に投稿可能な文字数かどうかをチェックする",
            "parameters": {
                "type": "object",
                "properties": {
                    "text": {
                        "type": "string",
                        "description": "投稿予定のテキスト"},
                    },
                },
            "required": ["text"]
            },
        }
    ]

messages=[
    {"role": "system", "content": "あなたは有能なSNSマーケターです。"},
    {"role": "user",      "content":   f"""
    以下のTwitter投稿文の文字数をcheck_tweet_len関数でチェックし、投稿可能な文字数まで調整してください。
    出力は改行を含めて修正文のみ出力し、コメントや説明などは省いてください。

    {sns_text}
    """
    }
]

# 1回目のFC応答
completion = client.chat.completions.create(
    model="gpt-4-0125-preview",
    messages=messages,
    temperature=1,
    max_tokens=1000,
    tools=tools,
    tool_choice="auto"
)

print("1回目のFCレスポンス:", completion.choices[0].message)

second_response = completion.choices[0].message
tool_calls = second_response.tool_calls
print("設定されたtool_calls:", tool_calls)

# tool_callsの指定があった場合にmessagesに指示を追加する
if tool_calls:
    available_functions = {
        "check_tweet_len": check_tweet_len
    }

    messages.append(second_response)
    print(" tool_call関数実施前のmessages:", messages)

    # tool_callsが複数ある場合の処理
    for tool_call in tool_calls:
            function_name = tool_call.function.name
            function_to_call = available_functions[function_name]

            if function_name == "check_tweet_len":
                arguments = json.loads(tool_call.function.arguments)
                function_response = function_to_call(arguments["text"]) #ここで関数を実行
                print("function_response", function_response)
            else:
                function_response = "function not found"

            messages.append(
                {
                    "tool_call_id": tool_call.id,
                    "role": "tool",
                    "name": function_name,
                    "content": function_response, #関数からの戻り値
                }
            )
            print(" tool_call関数の結果を入れたmessages:", messages)

    second_response = client.chat.completions.create(
    model="gpt-4-0125-preview",
    messages=messages
    )
    print("2回目のレスポンス:", second_response.choices[0].message.content)
    gpt_res = second_response.choices[0].message.content

初回の出力を入れなくてもFunction Callingはこんなにコードが長くなってしまいます。

これをDifyであれば、複雑なコード処理なしでクリックだけで実装することが可能です。

Function Calling

今回紹介するものは、前回①で解説したparse_tweet関数をエージェントに外部関数として使わせるという流れになります。

ちなみにFunction Callingの重要なポイントは、関数の実行そのものは生成AIは一切関与しないという点です。

Difyで関数を実行する手段は今のところ、Codeブロックの中でコードを実行する方法が上げられます。

しかしCodeブロックは、現状ライブラリのインストールが3種(jinja2、httpx、requests)しか対応していません。よって「!pip install twitter-text-parser」は使えず、このparse_tweet関数は使えません。

このような場合、この関数をAPIサーバーとして公開し、外部カスタムツールから使う方法であれば対応が可能です。

Difyでの外部APIは「ツール」という形で、様々なものが用意されています。

このツールは、カスタムツールとして自由にユーザーが追加することが可能です。

ここに先程のparse_tweet機能を追加すれば、生成AIがXの文字数チェックを自動的に行うことができるようになるわけです。

その方法を段階ごとに解説します。

Difyで自作APIを叩く方法

①コードファイルをサーバーにデプロイする

まずparse_tweetのPythonコードを外部サーバーにアップロードします。

今回はAWS Lambdaを使ってみたいと思います(GoogleならCloud Functionsが同様の機能だと思います)。

プロセスとしては以下のような流れになります。

Difyで自作APIを叩く

ローカルでpip installなどを実行し作ったファイルをまるまるzip保存し、AWS Lambdaにアップロードします。

なおこうしたAWS Lambdaの詳しい操作方法など、前提知識は全くない状態でしたが、全てClaudeが教えてくれました。

生成AI時代は『良くわからないけどまずやってみてエラーをAIに報告する』のが得策だと思います。


②APIサーバーを立てる

ファイルをサーバーにアップロードした後は、このコードにネット経由でアクセスするため、APIとして公開する流れになります。

APIサーバーはいくつかあるようですが、ここではAmazon Gatewayというものを使ってみます。

ちなみに各社のサービス名称をClaudeに聞いたらこれまた一発で教えてくれました。今回はAmazonのAPI管理とサーバレス関数を使ったことになります。

APIは、URLでアクセスすることでこのコード実行結果を取得するものです。requestsなどでデータが戻ってきたら成功です。

③Dify用のOPEN APIスキーマを作る

APIサーバーが立てられたら、次はDifyのLLMでこのAPIにアクセスするための説明書(スキーマ)を作成します。

これはGPTsでも使われている手法で、生成AIに先程のparse_tweet関数のコードと共に「このコードを呼び出すOPEN APIスキーマを作って」と入れるだけでほぼ完成したものが出力されます(エラー出たらAIに戻しましょう)。

openapi: 3.0.0
info:
  title: Tweet Length Checker API
  description: API to check if a given text meets Twitter's length requirements
  version: 1.0.2

servers:
  - url: https://xxx.xx.xx

paths:
  /check:
    post:  
      summary: Check tweet length
      description: Checks if the provided text meets Twitter's length requirements
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                text:
                  type: string
                  description: The text to be checked for Twitter length requirements
              required:
                - text
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TweetCheckResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

components:
  schemas:
    TweetCheckResponse:
      type: object
      properties:
        message:
          type: string
          description: Result message indicating if the text meets Twitter's requirements
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: Error message describing the issue

上記のようなコードが出力されます。

これをDifyのカスタムコードのスキーマ欄に貼り付ければ準備完了です。

エージェントで使う

この作ったカスタムツールをエージェントで使います。

エージェントはツールに関して、

  1. 使用するかどうかの判断
  2. 実行(正確にはAPIリクエスト)

を行うことが可能です。

このツールを有効化することで、指定文字数に収まる投稿が完成するまで、出力・チェック・修正を繰り返し行うわけです。

  1. SNSの投稿文章を作らせる(文字数など条件はある程度プロンプトで指定しておく)
  2. ツールで文字数をチェックさせる(外部APIの使用)
  3. 長過ぎたら修正する(以後繰り返し)

戻り値には具体的な改善ポイントを入れる

①の解説にてparse_tweet関数には、戻り値に具体的な改善ポイントを入れたほうが良いと記載しましたが、これはFunction Callingにおいては、戻り値がそのままLLMの入力変数となるからです。

戻り値が「文字数が多い」だけでなく、「文字数が今n文字なので280文字以下にしてください」と具体的な指示を入れておくことで、「出力→評価→再修正」を繰り返し実行することができるわけです(Difyの場合は現在、一つの関数を最大5回まで繰り返し実行可能のようです)。

おすすめの組み込みツール

SNS投稿文の作成において、おすすめのツールをいくつかご紹介します。

current_time

current_timeは現在の日時を取得するものです。これを使わせることで、季節感などにも強くなり、「明日の投稿考えて」というような投げかけにも日時を考慮した回答が可能となります。

tavily_search

tavily

tavily_searchは、キーワードで検索し、検索結果をLLM向けに変換して取得するものです。会社アカウトであれば、ここで会社名などで検索させることで、会社の基本情報やニュースなどを取得した上で、内容を提案してもらえます。

※なお下記でも触れましたが、Difyのバージョンによってはtavily_searchのパラメーターが聞かないことがありますのでご注意ください。その場合は、独自ツールとしてAPIから設定すると問題なく動くと思います。

  生成AI(Dify)を活用した検索・情報収集のポイント Difyの様々な検索・情報収集ツールを実際に使い、精度を比較しながら細かく解説します。 広報・PR支援の株式会社ガーオン

jina_reader

jinareader

jina_readerは、URLを渡すことで、そのページ内容をLLM向けに取得するものです。上記Tavilyと違いこちらは入力変数がURLとなります。

もし既存のWebサイトなどの情報を参考にできるようなケースであれば、入力変数に商品ページやLPなどのURLを入れておけば、その内容を参考に、投稿内容を提案してもらうことができます。

以上、Difyのエージェントを活用したSNS投稿文章の作成方法の解説でした。

次回はRAGを活用した方法を解説します。

続きは以下。

  【Dify活用】生成AIでSNSの投稿を爆速で作成する方法③ RAGの活用 Dify技術を活用したSNS投稿作成の効率化方法(③RAGの活用)を解説します。 広報・PR支援の株式会社ガーオン


関連記事

広報・PRやプレスリリースまわりでお困りのことはございませんか?
多数の企業サポートを行ってきた当社が解決いたします。
お気軽にお問合せください。