diff --git a/docs/index.md b/docs/index.md index b948600..fdde40a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,13 +1,17 @@ # template-langgraph -## Operations - -see [test_all.sh](../scripts/test_all.sh) for all operations +## Overview ```shell -# Start Docker containers +# Set up environment docker compose up -d +``` + +## Testing +see [test_all.sh](../scripts/test_all.sh) for all operations + +```shell # Test all scripts bash scripts/test_all.sh ``` diff --git a/notebooks/chat_with_tools.ipynb b/notebooks/chat_with_tools.ipynb new file mode 100644 index 0000000..d260233 --- /dev/null +++ b/notebooks/chat_with_tools.ipynb @@ -0,0 +1,120 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "1f4d669f", + "metadata": {}, + "outputs": [], + "source": [ + "from template_langgraph.agents.chat_with_tools_agent.agent import ChatWithToolsAgent\n", + "\n", + "# Create an instance of the agent\n", + "agent = ChatWithToolsAgent().create_graph()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "21bd80ab", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--------------------\n", + "Event: {'chat_with_tools': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_dgZmuEHRra9AoPOF0eDk8hlu', 'function': {'arguments': '{\"keywords\": \"鬼灯 KABUTO 停止 原因 対策\"}', 'name': 'search_qdrant'}, 'type': 'function'}, {'index': 1, 'id': 'call_Ozsm6M8EKcfqBGTEz2AqHVE0', 'function': {'arguments': '{\"keywords\": \"鬼灯 KABUTO 停止 原因 対策\"}', 'name': 'search_elasticsearch'}, 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'model_name': 'gpt-4o-2024-11-20', 'system_fingerprint': 'fp_ee1d74bde0'}, id='run--c1e04748-5dee-4a87-be5d-44ac8904997d-0', tool_calls=[{'name': 'search_qdrant', 'args': {'keywords': '鬼灯 KABUTO 停止 原因 対策'}, 'id': 'call_dgZmuEHRra9AoPOF0eDk8hlu', 'type': 'tool_call'}, {'name': 'search_elasticsearch', 'args': {'keywords': '鬼灯 KABUTO 停止 原因 対策'}, 'id': 'call_Ozsm6M8EKcfqBGTEz2AqHVE0', 'type': 'tool_call'}])]}}\n", + "--------------------\n", + "Event: {'tools': {'messages': [ToolMessage(content='\"[QdrantOutput(file_name=\\'./data/qa_kabuto.csv\\', content=\\'q: 特定のアプリケーション「鬼灯」を実行すると、KABUTOのファンが急に停止し、無音になります。 a: 「鬼灯」は、その特殊な演算処理において、KABUTOの冷却システム「風魔の術」を一時的に停止させ、内部エネルギーの流れを最適化する機能を持っています。これは異常ではありません。ただし、無音状態が15分以上続く場合は、過熱の可能性があるため、アプリケーションを強制終了し、KABUTO本体の電源を一度切ってから再起動してください。\\'), QdrantOutput(file_name=\\'./data/qa_kabuto.csv\\', content=\\'q: KABUTOの電源ランプが、赤と青の交互点滅ではなく、緑色で点滅しています。 a: 通常、電源ランプは赤(待機中)と青(稼働中)の点滅を繰り返します。緑色の点滅は、KABUTOが「禅モード」に入っており、パフォーマンスを最小限に抑え、バックグラウンドでシステム自己修復を行っている状態を示します。この状態では、ユーザー操作はほとんど受け付けられません。このモードから強制的に脱出するには、KABUTO本体の「龍玉」ボタンを5秒以上長押ししてください。\\'), QdrantOutput(file_name=\\'./data/qa_kabuto.csv\\', content=\\'q: KABUTOの画面の隅に、時々「狐火」のような光の点が、不規則に現れては消えます。 a: 「狐火」は、KABUTOの演算コア「稲荷」が、膨大な量のタスクを処理しきれずに、一部の計算結果が視覚的なノイズとして現れている現象です。これは、システム負荷が高いことを示しています。この現象が頻繁に発生する場合は、バックグラウンドで動作している不要なアプリケーションを終了させるか、KABUTOを再起動してください。\\')]\"', name='search_qdrant', id='852006ec-9c76-432a-a8f0-ee9a675f5096', tool_call_id='call_dgZmuEHRra9AoPOF0eDk8hlu'), ToolMessage(content='\"[ElasticsearchOutput(file_name=\\'docs_kabuto.pdf\\', content=\\'docs_kabuto.md 2025-08-01\\\\\\\\n2 / 3\\\\\\\\nた場合、「虚無」エラーが表⽰され、ログインは拒否される。これは疲労やストレスによる精神状態の変化が原因で\\\\\\\\nある可能性があり、深呼吸による精神状態の安定化が解決策となる。\\\\\\\\n3.3 ネットワーク・通信\\\\\\\\nネットワークモジュール「隠れ蓑」は、外部からの不必要なスキャンを回避するため、デフォルトでステルスモード\\\\\\\\nで動作する。これにより、ネットワーク上の他のデバイスから認識されない状態となる。 KABUTO をネットワーク上\\\\\\\\nで可視化させるには、ネットワーク設定画⾯から「忍びの道」オプションを有効にする必要がある。\\\\\\\\n3.4 演算コア\\'), ElasticsearchOutput(file_name=\\'docs_kabuto.pdf\\', content=\\'docs_kabuto.md 2025-08-01\\\\\\\\n2 / 3\\\\\\\\nた場合、「虚無」エラーが表⽰され、ログインは拒否される。これは疲労やストレスによる精神状態の変化が原因で\\\\\\\\nある可能性があり、深呼吸による精神状態の安定化が解決策となる。\\\\\\\\n3.3 ネットワーク・通信\\\\\\\\nネットワークモジュール「隠れ蓑」は、外部からの不必要なスキャンを回避するため、デフォルトでステルスモード\\\\\\\\nで動作する。これにより、ネットワーク上の他のデバイスから認識されない状態となる。 KABUTO をネットワーク上\\\\\\\\nで可視化させるには、ネットワーク設定画⾯から「忍びの道」オプションを有効にする必要がある。\\\\\\\\n3.4 演算コア\\'), ElasticsearchOutput(file_name=\\'docs_kabuto.pdf\\', content=\\'る。これにより、漢字で表⽰されている特定のフォルダ名が、ひらがなとして読み取られる現象が発⽣する。この問\\\\\\\\n題を解消するには、システム設定にて「読み⽅優先モード」を⼀時的に無効化する必要がある。\\\\\\\\n4.2 ⼊⼒・ AI アシスタント\\\\\\\\n内蔵 AI アシスタント「ヤタガラス」は、ユーザーの⼊⼒内容を予測し、システムの基幹⾔語である「KABUTO 語」に\\\\\\\\n最適化しようとする機能を持つ。これにより、特定の⽂字が⾃動的にカタカナに変換される現象が発⽣する。この機\\\\\\\\n能を⼀時的に停⽌するには、⼊⼒中にCtrlキーとShiftキーを同時に押しながら「 KABUTO 」と⼊⼒する。\\\\\\\\n4.3 スクリーンショット機能\\')]\"', name='search_elasticsearch', id='36b609c3-edcf-4fc7-ad3f-c80dfb896cf1', tool_call_id='call_Ozsm6M8EKcfqBGTEz2AqHVE0')]}}\n", + "--------------------\n", + "Event: {'chat_with_tools': {'messages': [AIMessage(content='「鬼灯」を実行するとKABUTOが急に停止する問題について、以下の情報が得られました。\\n\\n### 原因\\n1. **「鬼灯」の特性**:\\n - 「鬼灯」は特異な演算処理を行い、KABUTOの冷却システム「風魔の術」を一時的に停止させ、内部エネルギーの流れを最適化する機能を持っています。これは異常ではありませんが、システム負荷が高まる可能性があります。\\n\\n2. **過熱の可能性**:\\n - 無音状態が15分以上続く場合、過熱が原因でシステムが停止する可能性があります。\\n\\n3. **「禅モード」への移行**:\\n - KABUTOが「禅モード」に入ると、パフォーマンスを最小限に抑え、自己修復を行う状態になります。この場合、ユーザー操作がほとんど受け付けられません。\\n\\n### 対策\\n1. **システムの再起動**:\\n - 「鬼灯」実行後に無音状態が長時間続く場合、アプリケーションを強制終了し、KABUTO本体の電源を一度切ってから再起動してください。\\n\\n2. **「禅モード」からの脱出**:\\n - KABUTO本体の「竜玉」ボタンを5秒以上長押しすることで、「禅モード」から強制的に脱出できます。\\n\\n3. **冷却システムの確認**:\\n - 冷却システム「風魔の術」が正常に動作しているか確認してください。必要に応じて、システム設定を見直してください。\\n\\n4. **不要なアプリケーションの終了**:\\n - システム負荷を軽減するため、バックグラウンドで動作している不要なアプリケーションを終了させてください。\\n\\nこれらの対策を試しても問題が解決しない場合、KABUTOのサポートチームに連絡することをお勧めします。', additional_kwargs={}, response_metadata={'finish_reason': 'stop', 'model_name': 'gpt-4o-2024-11-20', 'system_fingerprint': 'fp_ee1d74bde0'}, id='run--ffeb926c-8451-484b-a052-a6a396b4cc67-0')]}}\n" + ] + } + ], + "source": [ + "question = \"「鬼灯」を実行すると、KABUTOが急に停止します。原因と対策を教えてください。\"\n", + "\n", + "# Stream the agent's response to the question\n", + "for event in agent.stream(\n", + " input={\n", + " \"messages\": [\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": question,\n", + " }\n", + " ],\n", + " }\n", + "):\n", + " print(\"-\" * 20)\n", + " print(f\"Event: {event}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "53219c94", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--------------------\n", + "Event: {'chat_with_tools': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_b3sbZHFfCd5ZiuufVBDrksGu', 'function': {'arguments': '{\"requirements\":\"京都から東京への旅行プランを作成してください。\"}', 'name': 'run_dify_workflow'}, 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'model_name': 'gpt-4o-2024-11-20', 'system_fingerprint': 'fp_ee1d74bde0'}, id='run--2edce6b7-e252-47c6-b05b-9c5d51f546d1-0', tool_calls=[{'name': 'run_dify_workflow', 'args': {'requirements': '京都から東京への旅行プランを作成してください。'}, 'id': 'call_b3sbZHFfCd5ZiuufVBDrksGu', 'type': 'tool_call'}])]}}\n", + "--------------------\n", + "Event: {'tools': {'messages': [ToolMessage(content='\"response={\\'task_id\\': \\'b9adea52-c9dd-4bf6-a5be-bbbc4b619e06\\', \\'workflow_run_id\\': \\'31fb862d-d30d-45c4-93a2-2924018f95b4\\', \\'data\\': {\\'id\\': \\'31fb862d-d30d-45c4-93a2-2924018f95b4\\', \\'workflow_id\\': \\'2d97261d-6f0e-4c1e-9223-993a96e676b8\\', \\'status\\': \\'succeeded\\', \\'outputs\\': {\\'text\\': \\'ええやん!ほな京都から東京への旅行プラン考えてみるわな。関西弁でしゃべるさかい、気ぃつけて聞いてや~。\\\\\\\\n\\\\\\\\n---\\\\\\\\n\\\\\\\\n**1日目:京都出発** \\\\\\\\n朝早よから京都駅発って新幹線「のぞみ」に乗るのがおすすめやで!せやけど、ちょっと節約したいんやったら「ひかり」でもええ感じや。新幹線乗ると東京まで2時間半くらいで着くし、めっちゃ早いなぁ。\\\\\\\\n\\\\\\\\n**2日目:東京観光** \\\\\\\\n東京やったら観光スポットがぎょうさんあるさかい、ちょっと絞らなあかんわ。\\\\\\\\n\\\\\\\\n- 【浅草】 \\\\\\\\n\\\\\\\\u3000まずは浅草や!雷門で写真撮って、仲見世通りでお土産買うたり、揚げまんじゅう食べたりしたらええと思うで。浅草寺もお参りして、運気アップや!\\\\\\\\n\\\\\\\\n- 【スカイツリー】 \\\\\\\\n\\\\\\\\u3000浅草から近いさかい、スカイツリーにも寄ったらええで。展望台から東京の景色を見渡せるし、ほんま感動するわ。\\\\\\\\n\\\\\\\\n- 【夜は渋谷】 \\\\\\\\n\\\\\\\\u3000夜は渋谷のスクランブル交差点に行ってみるとええで。人の多さにびっくりすると思うけど、これぞ東京や!ご飯もええ感じの居酒屋とかカフェがぎょうさんあるさかい、好きなとこ選んでな。\\\\\\\\n\\\\\\\\n**3日目:お台場と買い物** \\\\\\\\n- 【お台場】 \\\\\\\\n\\\\\\\\u3000お台場行ったら、レインボーブリッジ見たり、ヴィーナスフォートでショッピングしたり、海沿いでのんびりしたりできるで。ガンダムも見れるしな!\\\\\\\\n\\\\\\\\n- 【買い物】 \\\\\\\\n\\\\\\\\u3000東京駅周辺とか新宿で買い物するのもありやで。お土産買うたり、自分用にええもん探したりな。\\\\\\\\n\\\\\\\\n**4日目:帰り京都へ** \\\\\\\\n東京駅からまた新幹線乗って京都に帰るんやけど、帰りの新幹線では駅弁食べるのも楽しみやで。東京駅の駅弁は種類がようさんあるさかい、迷うぐらいや!\\\\\\\\n\\\\\\\\n---\\\\\\\\n\\\\\\\\nこんな感じのプランでどうやろ?まぁ、細かいとこは自分の好みに合わせて調整したらええと思うで!ええ旅行になることを祈っとるわ~!\\'}, \\'error\\': \\'\\', \\'elapsed_time\\': 8.108032, \\'total_tokens\\': 669, \\'total_steps\\': 3, \\'created_at\\': 1754332931, \\'finished_at\\': 1754332939}}\"', name='run_dify_workflow', id='1c54dc93-1c63-4d59-bdcd-74cdb034f550', tool_call_id='call_b3sbZHFfCd5ZiuufVBDrksGu')]}}\n", + "--------------------\n", + "Event: {'chat_with_tools': {'messages': [AIMessage(content='以下は京都から東京への旅行プランです。関西弁でまとめてみました!\\n\\n---\\n\\n### **1日目:京都出発**\\n朝早よから京都駅発って新幹線「のぞみ」に乗るのがおすすめやで!せやけど、ちょっと節約したいんやったら「ひかり」でもええ感じや。新幹線乗ると東京まで2時間半くらいで着くし、めっちゃ早いなぁ。\\n\\n---\\n\\n### **2日目:東京観光**\\n東京やったら観光スポットがぎょうさんあるさかい、ちょっと絞らなあかんわ。\\n\\n- **浅草** \\n まずは浅草や!雷門で写真撮って、仲見世通りでお土産買うたり、揚げまんじゅう食べたりしたらええと思うで。浅草寺もお参りして、運気アップや!\\n\\n- **スカイツリー** \\n 浅草から近いさかい、スカイツリーにも寄ったらええで。展望台から東京の景色を見渡せるし、ほんま感動するわ。\\n\\n- **夜は渋谷** \\n 夜は渋谷のスクランブル交差点に行ってみるとええで。人の多さにびっくりすると思うけど、これぞ東京や!ご飯もええ感じの居酒屋とかカフェがぎょうさんあるさかい、好きなとこ選んでな。\\n\\n---\\n\\n### **3日目:お台場と買い物**\\n- **お台場** \\n お台場行ったら、レインボーブリッジ見たり、ヴィーナスフォートでショッピングしたり、海沿いでのんびりしたりできるで。ガンダムも見れるしな!\\n\\n- **買い物** \\n 東京駅周辺とか新宿で買い物するのもありやで。お土産買うたり、自分用にええもん探したりな。\\n\\n---\\n\\n### **4日目:帰り京都へ**\\n東京駅からまた新幹線乗って京都に帰るんやけど、帰りの新幹線では駅弁食べるのも楽しみやで。東京駅の駅弁は種類がようさんあるさかい、迷うぐらいや!\\n\\n---\\n\\nこんな感じのプランでどうやろ?まぁ、細かいとこは自分の好みに合わせて調整したらええと思うで!ええ旅行になることを祈っとるわ~!', additional_kwargs={}, response_metadata={'finish_reason': 'stop', 'model_name': 'gpt-4o-2024-11-20', 'system_fingerprint': 'fp_ee1d74bde0'}, id='run--0740b1eb-e395-413d-87a0-f37aa5ae4746-0')]}}\n" + ] + } + ], + "source": [ + "question = \"Dify のワークフローで京都から東京への旅行プランを作成してください。\"\n", + "\n", + "# Stream the agent's response to the question\n", + "for event in agent.stream(\n", + " input={\n", + " \"messages\": [\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": question,\n", + " }\n", + " ],\n", + " }\n", + "):\n", + " print(\"-\" * 20)\n", + " print(f\"Event: {event}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d38858e3", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/templates.ipynb b/notebooks/templates.ipynb deleted file mode 100644 index 111046d..0000000 --- a/notebooks/templates.ipynb +++ /dev/null @@ -1,45 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "52e1990f-65ce-4f13-a55d-d645de8d7736", - "metadata": {}, - "source": [ - "# Templates\n", - "\n", - "```python\n", - "print(\"hello world!\")\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b1a7a812-9c7c-4072-ad6c-9bdff72a01e8", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.8" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/scripts/agent_runner.py b/scripts/agent_operator.py similarity index 100% rename from scripts/agent_runner.py rename to scripts/agent_operator.py diff --git a/scripts/dify_operator.py b/scripts/dify_operator.py index 1a2e61b..0323d11 100644 --- a/scripts/dify_operator.py +++ b/scripts/dify_operator.py @@ -54,7 +54,7 @@ def run_workflow( ensure_ascii=False, ) ) - logger.info(f"Input: {response['data']['outputs']['requirements']}, Output: {response['data']['outputs']['text']}") + logger.info(f"Output: {response['data']['outputs']['text']}") if __name__ == "__main__": diff --git a/scripts/qdrant_operator.py b/scripts/qdrant_operator.py index 3a67f8f..f12e549 100644 --- a/scripts/qdrant_operator.py +++ b/scripts/qdrant_operator.py @@ -6,7 +6,7 @@ from template_langgraph.llms.azure_openais import AzureOpenAiWrapper from template_langgraph.loggers import get_logger -from template_langgraph.tools.qdrants import QdrantClientWrapper +from template_langgraph.tools.qdrant_tool import QdrantClientWrapper from template_langgraph.utilities.csv_loaders import CsvLoaderWrapper # Initialize the Typer application diff --git a/scripts/test_all.sh b/scripts/test_all.sh index db83a81..d859cab 100644 --- a/scripts/test_all.sh +++ b/scripts/test_all.sh @@ -1,5 +1,11 @@ #!/bin/bash +# Stop on errors, undefined variables, and pipe failures +set -euo pipefail + +# Run Docker Compose to set up the environment +docker compose up -d --wait + # Qdrant uv run python scripts/qdrant_operator.py --help uv run python scripts/qdrant_operator.py delete-collection --collection-name qa_kabuto --verbose @@ -24,7 +30,7 @@ AGENT_NAMES=( "task_decomposer_agent" ) for AGENT_NAME in "${AGENT_NAMES[@]}"; do - uv run python scripts/agent_runner.py png --name "$AGENT_NAME" --verbose --output "generated/${AGENT_NAME}.png" + uv run python scripts/agent_operator.py png --name "$AGENT_NAME" --verbose --output "generated/${AGENT_NAME}.png" done ## Run agents @@ -38,5 +44,8 @@ NAME_QUESTION_ARRAY=( for NAME_QUESTION in "${NAME_QUESTION_ARRAY[@]}"; do IFS=':' read -r AGENT_NAME QUESTION <<< "$NAME_QUESTION" echo "Running agent: $AGENT_NAME with question: $QUESTION" - uv run python scripts/agent_runner.py run --name "$AGENT_NAME" --verbose --question "$QUESTION" + uv run python scripts/agent_operator.py run --name "$AGENT_NAME" --verbose --question "$QUESTION" done + +# Clean up Docker Compose environment +docker compose down --remove-orphans diff --git a/template_langgraph/agents/chat_with_tools_agent/agent.py b/template_langgraph/agents/chat_with_tools_agent/agent.py index 18a975e..89cd856 100644 --- a/template_langgraph/agents/chat_with_tools_agent/agent.py +++ b/template_langgraph/agents/chat_with_tools_agent/agent.py @@ -6,8 +6,9 @@ from template_langgraph.agents.chat_with_tools_agent.models import AgentState from template_langgraph.llms.azure_openais import AzureOpenAiWrapper from template_langgraph.loggers import get_logger +from template_langgraph.tools.dify_tool import run_dify_workflow from template_langgraph.tools.elasticsearch_tool import search_elasticsearch -from template_langgraph.tools.qdrants import search_qdrant +from template_langgraph.tools.qdrant_tool import search_qdrant logger = get_logger(__name__) @@ -39,6 +40,11 @@ def __call__(self, inputs: dict): class ChatWithToolsAgent: def __init__(self): self.llm = AzureOpenAiWrapper().chat_model + self.tools = [ + run_dify_workflow, + search_qdrant, + search_elasticsearch, + ] def create_graph(self): """Create the main graph for the agent.""" @@ -50,10 +56,7 @@ def create_graph(self): workflow.add_node( "tools", BasicToolNode( - tools=[ - search_qdrant, - search_elasticsearch, - ] + tools=self.tools, ), ) @@ -78,10 +81,7 @@ def chat_with_tools(self, state: AgentState) -> AgentState: """Chat with tools using the state.""" logger.info(f"Chatting with tools using state: {state}") llm_with_tools = self.llm.bind_tools( - tools=[ - search_qdrant, - search_elasticsearch, - ], + tools=self.tools, ) return { "messages": [ diff --git a/template_langgraph/agents/kabuto_helpdesk_agent/agent.py b/template_langgraph/agents/kabuto_helpdesk_agent/agent.py index a354461..b7341aa 100644 --- a/template_langgraph/agents/kabuto_helpdesk_agent/agent.py +++ b/template_langgraph/agents/kabuto_helpdesk_agent/agent.py @@ -2,8 +2,9 @@ from template_langgraph.llms.azure_openais import AzureOpenAiWrapper from template_langgraph.loggers import get_logger +from template_langgraph.tools.dify_tool import run_dify_workflow from template_langgraph.tools.elasticsearch_tool import search_elasticsearch -from template_langgraph.tools.qdrants import search_qdrant +from template_langgraph.tools.qdrant_tool import search_qdrant logger = get_logger(__name__) @@ -13,6 +14,7 @@ def __init__(self, tools=None): if tools is None: # Default tool for searching Qdrant tools = [ + run_dify_workflow, search_qdrant, search_elasticsearch, # Add other tools as needed diff --git a/template_langgraph/tools/dify_tool.py b/template_langgraph/tools/dify_tool.py index e26936e..c44c0e3 100644 --- a/template_langgraph/tools/dify_tool.py +++ b/template_langgraph/tools/dify_tool.py @@ -1,6 +1,8 @@ from functools import lru_cache import httpx +from langchain.tools import tool +from pydantic import BaseModel, Field from pydantic_settings import BaseSettings, SettingsConfigDict @@ -48,3 +50,36 @@ def run_workflow( ) response.raise_for_status() return response.json() + + +class DifyWorkflowInput(BaseModel): + requirements: str = Field( + default="生成 AI のサービス概要を教えてください。日本語でお願いします", + description="Requirements for running the Dify workflow", + ) + + +class DifyWorkflowOutput(BaseModel): + response: dict = Field(description="Output data from the Dify workflow") + + +@tool(args_schema=DifyWorkflowInput) +def run_dify_workflow( + requirements: str = "生成 AI のサービス概要を教えてください。日本語でお願いします", +) -> DifyWorkflowOutput: + """ + Difyワークフローを実行します。 + 指定された入力パラメータでワークフローを実行し、結果を返します。 + """ + wrapper = DifyClientWrapper() + response = wrapper.run_workflow( + inputs={ + "inputs": { + "requirements": requirements, + }, + "response_mode": "blocking", + "user": "abc-123", + } + ) + + return DifyWorkflowOutput(response=response) diff --git a/template_langgraph/tools/qdrants.py b/template_langgraph/tools/qdrant_tool.py similarity index 100% rename from template_langgraph/tools/qdrants.py rename to template_langgraph/tools/qdrant_tool.py