【LLM-agent】(task6)构建教程编写智能体

note

  • 构建教程编写智能体

文章目录

  • note
  • 一、功能需求
  • 二、相关代码
    • (1)定义生成教程的目录 Action 类
    • (2)定义生成教程内容的 Action 类
    • (3)定义教程编写智能体
    • (4)交互式操作调用教程编写智能体
  • 三、Python小细节
  • Reference

一、功能需求

功能:输入教程主题,然后自动生成完整的教程内容
思路:先通过 LLM 大模型生成教程的目录,再对目录按照二级标题进行分块,对于每块目录按照标题生成详细内容,最后再将标题和内容进行拼接。分块的设计解决了 LLM 大模型长文本的限制问题。

二、相关代码

(1)定义生成教程的目录 Action 类

定义 WriteDirectoryAction 类,继承自 BaseAction。该类的主要功能是生成一个教程的目录结构。具体来说,它通过调用大语言模型(LLM)来根据给定的主题和语言生成一个符合特定格式的目录。

(2)定义生成教程内容的 Action 类

WriteContentAction 类用于生成教程内容。它的 __call__ 方法接收标题、章节、语言和目录数据,并构建一个内容提示,最后调用 LLM 生成相应的内容。

(3)定义教程编写智能体

定义 TutorialAssistant 类,继承自 BaseAgent,用于生成教程内容。其主要功能包括:

  • 初始化目录和内容生成的动作(WriteDirectoryActionWriteContentAction
  • _generate_tutorial 方法根据目录数据生成完整的教程内容包括目录和每个章节的详细内容
  • _add_tutorial_example 方法为助手添加一个示例任务并展示如何生成一个 Python 教程的目录和内容。最终调用 __call__ 方法处理生成教程的任务。它从任务中提取主题,生成目录结构,然后生成完整的教程内容,并将结果保存到本地。

(4)交互式操作调用教程编写智能体

在主程序中,创建 TutorialAssistant 实例并调用其 __call__ 方法,实现交互式生成教程的功能。用户可以输入要创建的教程主题,然后调用 TutorialAssistant 生成相应的教程内容,并将结果保存到本地文件。

import os
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()
# 初始化变量
base_url = None
chat_model = None
api_key = None

# 使用with语句打开文件,确保文件使用完毕后自动关闭
env_path = ".env.txt"
with open(env_path, 'r') as file:
    # 逐行读取文件
    for line in file:
        # 移除字符串头尾的空白字符(包括'\n')
        line = line.strip()
        # 检查并解析变量
        if "base_url" in line:
            base_url = line.split('=', 1)[1].strip().strip('"')
        elif "chat_model" in line:
            chat_model = line.split('=', 1)[1].strip().strip('"')
        elif "ZHIPU_API_KEY" in line:
            api_key = line.split('=', 1)[1].strip().strip('"')
        elif "BOCHA_API_KEY" in line:
            BOCHA_API_KEY = line.split('=', 1)[1].strip().strip('"')

# 打印变量以验证
print(f"base_url: {base_url}")
print(f"chat_model: {chat_model}")
print(f"ZHIPU_API_KEY: {api_key}")


from typing import List, Dict
from zigent.llm.agent_llms import LLM
from zigent.actions import BaseAction, ThinkAct, FinishAct
from zigent.agents import BaseAgent
from zigent.commons import TaskPackage, AgentAct
from zigent.actions.InnerActions import INNER_ACT_KEY
from datetime import datetime
import json


llm = LLM(api_key=api_key, base_url=base_url, model_name=chat_model)
response = llm.run("你是谁?")
print(response)

# 一、定义生成教程的目录 Action 类
class WriteDirectoryAction(BaseAction):
    """Generate tutorial directory structure action"""
    def __init__(self) -> None:
        action_name = "WriteDirectory"
        action_desc = "Generate tutorial directory structure"
        params_doc = {
            "topic": "(Type: string): The tutorial topic name",
            "language": "(Type: string): Output language (default: '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.llm_chain.invoke({"prompt": directory_prompt})
        directory_data = llm.run(prompt=directory_prompt)  # 注意这里传入的是prompt参数
        
        try:
            directory_data = json.loads(directory_data)
        except:
            directory_data = {"title": topic, "directory": []}
            
        return {
            "topic": topic,
            "language": language,
            "directory_data": directory_data
        }
  

# 二、定义生成教程内容的 Action 类
class WriteContentAction(BaseAction):
    """Generate tutorial content action"""
    def __init__(self) -> None:
        action_name = "WriteContent"
        action_desc = "Generate detailed tutorial content based on directory structure"
        params_doc = {
            "title": "(Type: string): The section title",
            "chapter": "(Type: string): The chapter title",
            "directory_data": "(Type: dict): The complete directory structure", 
            "language": "(Type: string): Output language (default: '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.llm_chain.invoke({"prompt": content_prompt})
        content = llm.run(prompt=content_prompt) 
        return content
    

# 三、定义教程编写智能体
class TutorialAssistant(BaseAgent):
    """Tutorial generation assistant that manages directory and content creation"""
    def __init__(
        self,
        llm: LLM, # BaseLLM,
        language: str = "Chinese"
    ):
        name = "TutorialAssistant"
        role = """You are a professional tutorial writer. You can create well-structured, 
        comprehensive tutorials on various topics. You excel at organizing content logically 
        and explaining complex concepts clearly."""
        
        super().__init__(
            name=name,
            role=role,
            llm=llm,
        )
        
        self.language = language
        self.directory_action = WriteDirectoryAction()
        self.content_action = WriteContentAction()
    
        # Add example for the tutorial assistant
        self._add_tutorial_example()
        
    def _generate_tutorial(self, directory_data: Dict) -> str:
        """Generate complete tutorial content based on directory structure"""
        full_content = []
        title = directory_data["title"]
        full_content.append(f"# {title}\n")
        
        # Generate table of contents
        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")
        
        # Generate content for each section
        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):
        """Process the tutorial generation task"""
        # Extract topic from task
        topic = task.instruction.split("Create a ")[-1].split(" tutorial")[0]
        if not topic:
            topic = task.instruction
            
        # Generate directory structure
        directory_result = self.directory_action(
            topic=topic,
            language=self.language
        )

        print(directory_result)
        
        # Generate complete tutorial
        tutorial_content = self._generate_tutorial(directory_result["directory_data"])

        # Save the result
        task.answer = tutorial_content
        task.completion = "completed"
        
        return task

    def _add_tutorial_example(self):
        """Add an illustration example for the tutorial assistant"""
        exp_task = "Create a Python tutorial for beginners"
        exp_task_pack = TaskPackage(instruction=exp_task)
        topic = "Python基础教程"

        act_1 = AgentAct(
            name=ThinkAct.action_name,
            params={INNER_ACT_KEY: """First, I'll create a directory structure for the Python tutorial, 
            then generate detailed content for each section."""}
        )
        obs_1 = "OK. I'll start with the directory structure."

        act_2 = AgentAct(
            name=self.directory_action.action_name,
            params={
                "topic": topic, 
                "language": self.language
            }
        )
        obs_2 = """{"title": "Python基础教程", "directory": [
            {"第一章:Python介绍": ["1.1 什么是Python", "1.2 环境搭建"]},
            {"第二章:基础语法": ["2.1 变量和数据类型", "2.2 控制流"]}
        ]}"""

        act_3 = AgentAct(
            name=self.content_action.action_name,
            params={
                "title": "什么是Python",
                "chapter": "第一章:Python介绍",
                "directory_data": json.loads(obs_2),
                "language": self.language
            }
        )
        obs_3 = """# 第一章:Python介绍\n## 什么是Python\n\nPython是一种高级编程语言..."""

        act_4 = AgentAct(
            name=FinishAct.action_name,
            params={INNER_ACT_KEY: "Tutorial structure and content generated successfully."}
        )
        obs_4 = "Tutorial generation task completed successfully."

        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
        )


# 四、交互式操作调用教程编写智能体
if __name__ == "__main__":
    assistant = TutorialAssistant(llm=llm)

     # 交互式生成教程
    FLAG_CONTINUE = True
    while FLAG_CONTINUE:
        input_text = input("What tutorial would you like to create?\n")
        task = TaskPackage(instruction=input_text)
        result = assistant(task)
        print("\nGenerated Tutorial:\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("\nDo you want to create another tutorial? (y/n): ").lower() != "y":
            FLAG_CONTINUE = False

输出教程的主题后就会生成markdown格式的教程文档,我输的music,由于是先生成教程的大标题和各种子标题,再逐个将标题对应的内容生成,这样保证了长文本的生成,从结果来看确实有一大坨字数:
在这里插入图片描述

三、Python小细节

在Python中,__call__ 方法允许一个类的实例表现得像函数一样,这意味着你可以直接调用一个实例,就像它是函数一样。当你定义了 __call__ 方法后,这个类的实例就可以被当作一个可调用的对象。
下面是一个简单的例子来说明 __call__ 方法是如何工作的:

class CallableClass:
    def __init__(self, value):
        self.value = value
    def __call__(self, addend):
        return self.value + addend
# 创建一个CallableClass的实例
callable_instance = CallableClass(10)
# 直接调用实例,就像它是函数一样
result = callable_instance(5)  # 这将调用 __call__ 方法
print(result)  # 输出 15

在这个例子中,CallableClass 有一个 __call__ 方法,它接受一个参数 addend,并返回实例属性 valueaddend 的和。

以下是 __call__ 方法的一些用途:

  1. 创建函数工厂:你可以创建一个类,其实例是定制化的函数。
  2. 封装函数调用:你可以使用类来封装函数调用,提供额外的逻辑或状态管理。
  3. 装饰器:在编写装饰器时,有时会使用 __call__ 方法来定义装饰器如何调用原始函数。
  4. 回调函数:在需要传递回调函数的场景中,你可以使用具有 __call__ 方法的对象,这样可以在回调中保持状态。

Reference

[1] https://github.com/datawhalechina/wow-agent
[2] https://www.datawhale.cn/learn/summary/86
[3] https://open.bochaai.com/
[4] 官方文档:https://docs.cloud.llamaindex.ai/
[5] 出题智能体、metagpt:https://www.cnblogs.com/HYLOVEYOURSELF/p/18691941
[6] 教程编写智能体:https://www.cnblogs.com/HYLOVEYOURSELF/p/18680532

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/963509.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++游戏开发实战:从引擎架构到物理碰撞

📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 1. 引言 C 是游戏开发中最受欢迎的编程语言之一,因其高性能、低延迟和强大的底层控制能力,被广泛用于游戏…

Time Constant | RC、RL 和 RLC 电路中的时间常数

注:本文为 “Time Constant” 相关文章合辑。 机翻,未校。 How To Find The Time Constant in RC and RL Circuits June 8, 2024 💡 Key learnings: 关键学习点: Time Constant Definition: The time constant (τ) is define…

DeepSeek Janus-Pro:多模态AI模型的突破与创新

近年来,人工智能领域取得了显著的进展,尤其是在多模态模型(Multimodal Models)方面。多模态模型能够同时处理和理解文本、图像等多种类型的数据,极大地扩展了AI的应用场景。DeepSeek(DeepSeek-V3 深度剖析:…

w188校园商铺管理系统设计与实现

🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…

DeepSeek R1本地化部署 Ollama + Chatbox 打造最强 AI 工具

🌈 个人主页:Zfox_ 🔥 系列专栏:Linux 目录 一:🔥 Ollama 🦋 下载 Ollama🦋 选择模型🦋 运行模型🦋 使用 && 测试 二:🔥 Chat…

图漾相机——Sample_V1示例程序

文章目录 1.SDK支持的平台类型1.1 Windows 平台1.2 Linux平台 2.SDK基本知识2.1 SDK目录结构2.2 设备组件简介2.3 设备组件属性2.4 设备的帧数据管理机制2.5 SDK中的坐标系变换 3.Sample_V1示例程序3.1 DeviceStorage3.2 DumpCalibInfo3.3 NetStatistic3.4 SimpleView_SaveLoad…

DeepSeek 遭 DDoS 攻击背后:DDoS 攻击的 “千层套路” 与安全防御 “金钟罩”

当算力博弈升级为网络战争:拆解DDoS攻击背后的技术攻防战——从DeepSeek遇袭看全球网络安全新趋势 在数字化浪潮席卷全球的当下,网络已然成为人类社会运转的关键基础设施,深刻融入经济、生活、政务等各个领域。从金融交易的实时清算&#xf…

小程序项目-购物-首页与准备

前言 这一节讲一个购物项目 1. 项目介绍与项目文档 我们这里可以打开一个网址 https://applet-base-api-t.itheima.net/docs-uni-shop/index.htm 就可以查看对应的文档 2. 配置uni-app的开发环境 可以先打开这个的官网 https://uniapp.dcloud.net.cn/ 使用这个就可以发布到…

深入解析Python机器学习库Scikit-Learn的应用实例

深入解析Python机器学习库Scikit-Learn的应用实例 随着人工智能和数据科学领域的迅速发展,机器学习成为了当下最炙手可热的技术之一。而在机器学习领域,Python作为一种功能强大且易于上手的编程语言,拥有庞大的生态系统和丰富的机器学习库。其…

大模型训练(5):Zero Redundancy Optimizer(ZeRO零冗余优化器)

0 英文缩写 Large Language Model(LLM)大型语言模型Data Parallelism(DP)数据并行Distributed Data Parallelism(DDP)分布式数据并行Zero Redundancy Optimizer(ZeRO)零冗余优化器 …

在亚马逊云科技上用Stable Diffusion 3.5 Large生成赛博朋克风图片(上)

背景介绍 在2024年的亚马逊云科技re:Invent大会上提前预告的Stable Diffusion 3.5 Large,现在已经在Amazon Bedrock上线了!各位开发者们现在可以使用该模型,根据文本提示词文生图生成高质量的图片,并且支持多种图片风格生成&…

java练习(5)

ps:题目来自力扣 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这…

【力扣】438.找到字符串中所有字母异位词

AC截图 题目 思路 我一开始是打算将窗口内的s子字符串和p字符串都重新排序&#xff0c;然后判断是否相等&#xff0c;再之后进行窗口滑动。不过缺点是会超时。 class Solution { public:vector<int> findAnagrams(string s, string p) {vector<int> vec;if(s.siz…

DeepSeek回答禅宗三重境界重构交易认知

人都是活在各自心境里&#xff0c;有些话通过语言去交流&#xff0c;还是要回归自己心境内在的&#xff0c;而不是靠外在映射到股票和技术方法&#xff1b;比如说明天市场阶段是不修复不接力节点&#xff0c;这就是最高视角看整个市场&#xff0c;还有哪一句话能概括&#xff1…

C++进阶: 红黑树及map与set封装

红黑树总结整理 红黑色概述&#xff1a; 红黑树整理与AVL树类似&#xff0c;但在对树的平衡做控制时&#xff0c;AVL树会比红黑树更严格。 AVL树是通过引入平衡因子的概念进行对树高度控制。 红黑树则是对每个节点标记颜色&#xff0c;对颜色进行控制。 红黑树控制规则&…

BUUCTF_[网鼎杯 2020 朱雀组]phpweb(反序列化绕过命令)

打开靶场&#xff0c;,弹出上面的提示,是一个警告warning,而且页面每隔几秒就会刷新一次,根据warning中的信息以及信息中的时间一直在变,可以猜测是date()函数一直在被调用 查看页面源代码&#xff0c;没有什么有用的信息 Burp抓包一下 调用了date()函数并回显在页面上,参数fu…

pandas(二)读取数据

一、读取数据 示例代码 import pandaspeople pandas.read_excel(../002/People.xlsx) #读取People数据 print(people.shape) # 打印people表的行数、列数 print(people.head(3)) # 默认打印前5行,当前打印前3行 print("") print(people.tail(3)) # 默…

智慧物业管理系统实现社区管理智能化提升居民生活体验与满意度

内容概要 智慧物业管理系统&#xff0c;顾名思义&#xff0c;是一种将智能化技术融入社区管理的系统&#xff0c;它通过高效的手段帮助物业公司和居民更好地互动与沟通。首先&#xff0c;这个系统整合了在线收费、停车管理等功能&#xff0c;让居民能够方便快捷地完成日常支付…

二十三、集合类

Ⅰ . Set 类 01 Set 介绍 template < class T, // set::key_type/value_typeclass Compare less<T>, // set::key_compare/value_compareclass Alloc allocator<T> // set::allocator_type> class set; 通过插入新的元素来扩…

5.5.1 面向对象的基本概念

文章目录 基本概念面向对象的5个原则 基本概念 面向对象的方法&#xff0c;特点时其分析与设计无明显界限。虽然在软件开发过程中&#xff0c;用户的需求会经常变化&#xff0c;但客观世界对象间的关系是相对稳定的。对象是基本的运行实体&#xff0c;由数据、操作、对象名组成…