Hanah

Hanah

わお エージェント デイ10 Zigent実現チュートリアル スマートエージェントの作成

Reference:Datawhale wow agent day10
本節では、Zigent フレームワークを使用して、チュートリアルを作成するエージェントを実装します。このエージェントの主な機能は、チュートリアルのテーマを入力し、その後自動的に完全なチュートリアルコンテンツを生成することです。 設計思想:
まず、LLM 大モデルを使用してチュートリアルの目次を生成し、次に目次を二次タイトルに従って分割し、各ブロックの目次に従って詳細な内容を生成し、最後にタイトルと内容を結合します。この分割設計は、LLM 大モデルの長文制限の問題を解決します。

チュートリアルの目次を生成する Action クラスの定義#

WriteDirectoryAction クラスを定義し、BaseAction から継承します。このクラスの主な機能は、チュートリアルの目次構造を生成することです。具体的には、与えられたテーマと言語に基づいて特定の形式に従った目次を生成するために、大言語モデル(LLM)を呼び出します。

class WriteDirectoryAction(BaseAction):
    """チュートリアル目次構造生成アクション"""
    def __init__(self) -> None:
        action_name = "WriteDirectory"
        action_desc = "チュートリアル目次構造を生成"
        params_doc = {
            "topic": "(タイプ: 文字列): チュートリアルのテーマ名",
            "language": "(タイプ: 文字列): 出力言語 (デフォルト: 'Chinese')"
        }
        super().__init__(action_name, action_desc, params_doc)
        
    def __call__(self, **kwargs):
        topic = kwargs.get("topic", "")
        language = kwargs.get("language", "Chinese")
        
        directory_prompt = f"""
        テーマ"{topic}"のチュートリアル目次構造を生成してください。要求:
        1. 出力言語は{language}でなければなりません
        2. 以下の辞書形式に厳密に従って出力してください: {{"title": "xxx", "directory": [{{"章1": ["小節1", "小節2"]}}, {{"章2": ["小節3", "小節4"]}}]}}
        3. 目次の階層は合理的で、主目次と子目次を含む必要があります
        4. 各目次タイトルは実際の意味を持つ必要があります
        5. 不要な空白や改行を含めないでください
        """
        
        # LLMを呼び出して目次を生成
        directory_data = llm.run(directory_prompt)
        try:
            directory_data = json.loads(directory_data)
        except:
            directory_data = {"title": topic, "directory": []}
            
        return {
            "topic": topic,
            "language": language,
            "directory_data": directory_data
        }
  

チュートリアル内容を生成する Action クラスの定義#

WriteContentAction クラスは、チュートリアル内容を生成するために使用されます。その__call__メソッドは、タイトル、章、言語、目次データを受け取り、内容のプロンプトを構築し、最後に LLM を呼び出して対応する内容を生成します。

class WriteContentAction(BaseAction):
    """チュートリアル内容生成アクション"""
    def __init__(self) -> None:
        action_name = "WriteContent"
        action_desc = "目次構造に基づいて詳細なチュートリアル内容を生成"
        params_doc = {
            "title": "(タイプ: 文字列): セクションタイトル",
            "chapter": "(タイプ: 文字列): 章タイトル",
            "directory_data": "(タイプ: dict): 完全な目次構造", 
            "language": "(タイプ: 文字列): 出力言語 (デフォルト: 'Chinese')"
        }
        super().__init__(action_name, action_desc, params_doc)
        
    def __call__(self, **kwargs):
        title = kwargs.get("title", "")
        chapter = kwargs.get("chapter", "")
        language = kwargs.get("language", "Chinese")
        directory_data = kwargs.get("directory_data", {})
        
        content_prompt = f"""
        チュートリアル章の詳細な内容を生成してください:
        チュートリアルタイトル: {directory_data.get('title', '')}
        章: {chapter}
        小節: {title}
        
        要求:
        1. 内容は詳細かつ正確であること
        2. コード例が必要な場合は、標準規範に従って提供してください
        3. Markdown形式を使用してください
        4. 出力言語は{language}でなければなりません
        5. 内容の長さは適度で、通常500〜1000字の範囲であること
        """
        
        # LLMを呼び出して内容を生成
        content = llm.run(content_prompt)
        return content

チュートリアル作成エージェントの定義#

TutorialAssistant クラスを定義し、BaseAgent から継承します。チュートリアル内容を生成するために使用されます。その主な機能には、目次と内容生成のアクション(WriteDirectoryAction と WriteContentAction)の初期化、_generate_tutorial メソッドが目次データに基づいて目次と各章の詳細な内容を生成すること、_add_tutorial_example メソッドがアシスタントに例題を追加し、Python チュートリアルの目次と内容を生成する方法を示すことが含まれます。最終的に__call__メソッドを呼び出してチュートリアル生成タスクを処理します。タスクからテーマを抽出し、目次構造を生成し、次に完全なチュートリアル内容を生成し、結果をローカルに保存します。

class TutorialAssistant(BaseAgent):
    """目次と内容の作成を管理するチュートリアル生成アシスタント"""
    def __init__(
        self,
        llm: LLM,
        language: str = "Chinese"
    ):
        name = "TutorialAssistant"
        role = """あなたはプロのチュートリアルライターです。さまざまなトピックに関する構造化された、包括的なチュートリアルを作成できます。内容を論理的に整理し、複雑な概念を明確に説明するのが得意です。"""
        
        super().__init__(
            name=name,
            role=role,
            llm=llm,
        )
        
        self.language = language
        self.directory_action = WriteDirectoryAction()
        self.content_action = WriteContentAction()
    
        # チュートリアルアシスタントの例を追加
        self._add_tutorial_example()
        
    def _generate_tutorial(self, directory_data: Dict) -> str:
        """目次構造に基づいて完全なチュートリアル内容を生成"""
        full_content = []
        title = directory_data["title"]
        full_content.append(f"# {title}\n")
        
        # 目次を生成
        full_content.append("## 目次\n")
        for idx, chapter in enumerate(directory_data["directory"], 1):
            for chapter_title, sections in chapter.items():
                full_content.append(f"{idx}. {chapter_title}")
                for section_idx, section in enumerate(sections, 1):
                    full_content.append(f"   {idx}.{section_idx}. {section}")
        full_content.append("\n---\n")
        
        # 各セクションの内容を生成
        for chapter in directory_data["directory"]:
            for chapter_title, sections in chapter.items():
                for section in sections:
                    content = self.content_action(
                        title=section,
                        chapter=chapter_title,
                        directory_data=directory_data,
                        language=self.language
                    )
                    full_content.append(content)
                    full_content.append("\n---\n")
        
        return "\n".join(full_content)

    def __call__(self, task: TaskPackage):
        """チュートリアル生成タスクを処理"""
        # タスクからテーマを抽出
        topic = task.instruction.split("Create a ")[-1].split(" tutorial")[0]
        if not topic:
            topic = task.instruction
            
        # 目次構造を生成
        directory_result = self.directory_action(
            topic=topic,
            language=self.language
        )

        print(directory_result)
        
        # 完全なチュートリアルを生成
        tutorial_content = self._generate_tutorial(directory_result["directory_data"])

        # 結果を保存
        task.answer = tutorial_content
        task.completion = "completed"
        
        return task

    def _add_tutorial_example(self):
        """チュートリアルアシスタントのための例を追加"""
        exp_task = "初心者向けのPythonチュートリアルを作成する"
        exp_task_pack = TaskPackage(instruction=exp_task)
        topic = "Python基礎チュートリアル"

        act_1 = AgentAct(
            name=ThinkAct.action_name,
            params={INNER_ACT_KEY: """まず、Pythonチュートリアルの目次構造を作成し、次に各セクションの詳細な内容を生成します。"""}
        )
        obs_1 = "OK。目次構造から始めます。"

        act_2 = AgentAct(
            name=self.directory_action.action_name,
            params={
                "topic": topic, 
                "language": self.language
            }
        )
        obs_2 = """{"title": "Python基礎チュートリアル", "directory": [
            {"第1章:Python紹介": ["1.1 Pythonとは", "1.2 環境構築"]},
            {"第2章:基本文法": ["2.1 変数とデータ型", "2.2 制御フロー"]}
        ]}"""

        act_3 = AgentAct(
            name=self.content_action.action_name,
            params={
                "title": "Pythonとは",
                "chapter": "第1章:Python紹介",
                "directory_data": json.loads(obs_2),
                "language": self.language
            }
        )
        obs_3 = """# 第1章:Python紹介\n## Pythonとは\n\nPythonは高級プログラミング言語です..."""

        act_4 = AgentAct(
            name=FinishAct.action_name,
            params={INNER_ACT_KEY: "チュートリアルの構造と内容が正常に生成されました。"}
        )
        obs_4 = "チュートリアル生成タスクが正常に完了しました。"

        exp_act_obs = [(act_1, obs_1), (act_2, obs_2), (act_3, obs_3), (act_4, obs_4)]
        
        self.prompt_gen.add_example(
            task=exp_task_pack,
            action_chain=exp_act_obs
        )

インタラクティブな操作でチュートリアル作成エージェントを呼び出す#

メインプログラムでは、TutorialAssistant インスタンスを作成し、その__call__メソッドを呼び出してインタラクティブにチュートリアルを生成する機能を実現します。ユーザーは作成したいチュートリアルのテーマを入力し、その後 TutorialAssistant を呼び出して対応するチュートリアル内容を生成し、結果をローカルファイルに保存します。

if __name__ == "__main__":
    assistant = TutorialAssistant(llm=llm)

     # インタラクティブにチュートリアルを生成
    FLAG_CONTINUE = True
    while FLAG_CONTINUE:
        input_text = input("どのチュートリアルを作成したいですか?\n")
        task = TaskPackage(instruction=input_text)
        result = assistant(task)
        print("\n生成されたチュートリアル:\n")
        print(result.answer)

        # 出力ディレクトリを作成
        output_dir = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
        os.makedirs(output_dir, exist_ok=True)
        
        # ファイルを保存
        output_file = os.path.join(output_dir, f"{input_text}.md")
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write(result.answer)
        if input("\n別のチュートリアルを作成しますか? (y/n): ").lower() != "y":
            FLAG_CONTINUE = False

テスト結果#

基礎トポロジーのチュートリアルを生成:

image
長すぎるので完全には掲載しません。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。