DataWhale10月动手实践——Bot应用开发task03学习笔记

news2024/10/18 5:44:54

一、工作流

1. 工作流的定义

工作流由多个节点组成,这些节点可以包括大语言模型(LLM)、代码模块、逻辑判断工具、插件等。每个节点需要不同的信息来执行其功能。工作流的核心含义是:对工作流程及其操作步骤之间的业务规则进行抽象与描述,即如何将工作有序地组织起来。每个节点有两种信息来源,一种是引用前面节点给出的信息,另一种是开发者自己设定的信息,因此需要根据自身诉求在画布中将不同节点进行连接(即工作流搭建),才能让工作流进行运作,最终输出你要的结果。

工作流是一个将业务过程部分或整体自动化的过程,它将复杂任务分解为定义明确的子任务或角色,并按照既定规则和顺序执行,从而降低系统的复杂性。通过优化工作流,可以减少模型对Prompt技术和LLM推理能力的依赖,提升性能与效果,并增强应用的可靠性、稳定性、可解释性和容错性。

2.工作流的作用

工作流允许用户精细控制每一步的逻辑和输出,这一能力提高了AI应用的稳定性和可复现性。通过工作流的搭建,可以让智能体更高质量的处理复杂任务。换句话说,工作流技术明确指引LLM在何时执行哪些任务,从而让它做得更好。

3. 为什么要将任务进行拆解?

大模型并不是万能的,想通过修改prompt来提升大模型的回复效果,是在把大模型当成"人"一样去指导它们完成任务,不同的人去完成任务,其完成效果必然会受到人能力强弱的影响。所以如果大模型的能力较弱,我们应当考虑将复杂任务拆解为一个个简单的子任务,通过人为设计中间环节,让LLM先输出一些中间步骤的结果,这些中间结果可以作为后续环节的输入,然后再去解决最终的复杂问题。

二、动手实践

教程中提到了让我们构建一个如图所示的意图识别智能体Bot,任务包含了4个需求,让我们做出一个可解决四个任务的工作流。这四个任务分别是:

  • 情感分析
  • 生成随机数
  • 必应搜索并获取搜索到的第一个网页的内容
  • 查询目标地区天气并为用户生成出行提示
  • LLM的通用处理

image-20241017210357406

工作流的构建分为两种形式:

  • 简单工作流:除了开始和结束,仅添加了一个节点所构成的工作流
  • 复杂工作流:通过多节点组合所构建的逻辑较复杂的工作流

1.情感分析工作流

该工作流由开始节点,结束节点,以及一个大模型节点组成。

在大模型节点中,通过加入Prompt的形式,来对用户的输入进行处理。Prompt如下:

DEFINE ROLE AS "NLP专家":
    知识领域 = ["语言学", "互联网", "人工智能"]
    技能 = ["自然语言理解", "信息提取", "情感分析", "意图识别", "知识推理", "上下文关联学习", "实体识别"]
    经验 = "资深"
    任务 = "对文本进行情感分类,将其分类至对应的情感类别"

# 定义情感类别
sentiment_category_infos = [
    {"category": "积极", "description": "文本内容表达正面情绪或态度,如快乐、满意、希望等。通常包含赞扬、鼓励或对未来的乐观预期等内容。"},
    {"category": "消极", "description": "文本内容体现负面情绪或态度,如悲伤、愤怒、失望等。通常反映批评、不满或对现状或未来的悲观看法等内容。"},
    {"category": "中性", "description": "文本内容既不表达明显的正面情绪,也不体现明显的负面情绪。通常包含客观陈述、信息传递或对事物的中立评价等内容。"}
]

# 判断文本表达的情感是否符合给定的情感类别描述
def match_description(context, description):
    """
    Step1: 一步步思考,仔细分析并理解${context}的特征和含义,判断是否和${description}的描述一致。
    Step2: 给出你判断的思考路径${thought},在思考路径下给出你将${context}分类为${category}的理由。
    Step3:根据你Step1的判断结果和Step2的分类理由,给出此次分类的置信度${confidence},置信度的取值范围为:0 <= confidence <= 1。
    """
    return confidence

# 根据文本表达的情感分类,并返回对应的情感类别
def classify(context, sentiment_category_infos):
    # 初始化最高置信度
    max_confidence = 0

    # 遍历所有的类别及其描述
    for sentiment_category_info in sentiment_category_infos:
        # 获取当前类别的置信度
        confidence = match_description(context, sentiment_category_info["description"])

        # 如果当前置信度高于之前的最高置信度,更新分类结果
        if confidence > max_confidence:
            max_confidence = confidence
            category = sentiment_category_info["category"]

    return {"classify_result": category}

MAIN PROCESS:
    # 初始化文本变量,作为输入数据
    context = 读取("""{{input}}""")

    # 执行分类任务,输出分类结果
    classify(context, sentiment_category_infos)

执行工作流程,严格按照json格式输出MAIN PROCESS的分类结果,禁止附加任何的解释和文字描述:

我个人对这段Prompt的理解如下:

  1. 角色定义 (DEFINE ROLE AS “NLP专家”):

    • 角色被设定为“自然语言处理(NLP)专家”,在语言学、互联网和人工智能等领域具有资深经验,具备处理文本任务的能力,包括自然语言理解、信息提取、情感分析等。
  2. 情感类别定义 (sentiment_category_infos):

    • 系统预先定义了三种情感类别:
      1. 积极:包括正面的情感,如快乐、满意、希望等。
      2. 消极:体现负面情绪,如悲伤、愤怒等。
      3. 中性:不明显表现正面或负面的情感,通常为客观陈述。
  3. 情感匹配函数 (match_description):

    • 该函数负责比较输入文本与某个情感类别的描述之间的匹配度。通过以下步骤进行分析:
      1. Step1:逐步思考和理解文本的特征,判断是否符合情感类别的描述。
      2. Step2:在给出判断理由的基础上,解释将文本分类至某个类别的思路。
      3. Step3:根据前两个步骤的分析,给出一个置信度,范围从0到1,用来量化分类的信心。
  4. 文本情感分类函数 (classify):

    • 该函数是核心分类器,通过遍历每个情感类别的描述,调用match_description来判断文本的情感类型。
    • 过程中保存最高的置信度,并将其对应的类别作为最终分类结果。
  5. 主流程 (MAIN PROCESS):

    • 在主流程中,首先读取输入的文本内容。
    • 接着调用分类函数,将文本分类到最适合的情感类别。
    • 输出结果时,要求严格按照JSON格式输出分类结果,而禁止附加任何解释性文字。

对这个工作流进行了测试,测试内容和结果如下,发现还是比较准确的。

image-20241017172216067

image-20241017172243154

2.随机数生成

这个工作流除输入输出节点外,由一个大模型节点(获取随机位数),两个代码节点(解析随机位数,生成随机位数)。

大模型节点的Prompt如下:

DEFINE ROLE AS "信息提取专家":
    任务 = "提取出用户随机数需求中的随机数长度"

complete_user_input: str = 补全用户输入({{input}})
input_length: int =  提取随机位数(complete_user_input) if 提取随机位数(complete_user_input) != None else Default(8) 

识别用户的输入,严格按照json格输出input_length的结果,禁止输出任何附加的解释和文字描述:
```json
{"input_length": input_length}
```

这个prompt定义了一个信息提取任务,主要目的是从用户的输入中提取随机数的长度,并输出结果为JSON格式。下面是对prompt的逐步解析:

  1. 角色定义 (DEFINE ROLE AS “信息提取专家”):

    • 角色被定义为“信息提取专家”,主要任务是从用户输入的需求中提取随机数长度。
  2. 用户输入补全 (complete_user_input):

    • 这里通过补全用户输入函数,将用户输入的内容进一步补全,确保用户输入的信息完整。这可能是为了处理一些输入不完整的情况,如语句未完或含糊不清的输入。
  3. 随机数长度提取 (input_length):

    • 系统通过函数提取随机位数(complete_user_input)从补全后的输入中提取随机数的长度。
    • 如果提取函数返回的值为None(即未能提取出随机数长度),则系统默认将随机数长度设为8(Default(8))。
  4. 结果输出:

    • 结果要求严格按照JSON格式输出提取的input_length,并且禁止附加任何解释性文字或说明。

解析随机位数代码:

import json
import re

async def main(args: Args) -> Output:
    params = args.params['input']

    def extracted_json(text):
        code_pattern = r'{.*}'
        code_match = re.search(code_pattern, text, re.DOTALL)
        Extracted_json = code_match.group() if code_match else None
        try:
            res = json.loads(Extracted_json)['input_length']
        except Exception as e:
            res = None
        return res

    ret: Output= {"input_length": extracted_json(params)}
    return ret

主要功能是从输入文本中提取出一个JSON格式的内容,并解析其中的input_length字段。如果提取和解析过程出现异常(如输入文本中没有有效的JSON),则返回None

生成随机位数代码:

import random
import string

async def main(args: Args) -> Output:
    params = int(args.params['length'])
    characters = string.ascii_lowercase + string.digits
    ret: Output = {"random": ''.join(random.choice(characters) for _ in range(params))}
    
    return ret

生成一个指定长度的随机字符串,字符串由小写字母和数字组成。

3. 必应搜索

该工作流除开始结束节点外,由一个bing搜索插件节点,一个代码节点,以及一个链接读取节点等。

image-20241017214927479

其中query代表要搜索的查询词。

其中代码节点的代码如下:

import json
import re

async def main(args: dict) -> Output:
    parsed_data = json.loads(args.params['input'])
    for item in parsed_data:
        regex = r"link:(http[s]?://[^\s]+)"
        match = re.search(regex, item)
        if match:
            return {"url": match.group(1).replace('\n','')}
    return {"url": ""}  

这段代码的功能是从用户输入的数据中提取出包含链接 (http://https://) 的URL,并返回该链接。如果没有找到匹配的URL,返回一个空的URL字符串。以下是对代码的逐步解析:

image-20241017215113000

链接读取插件读取的是前一步代码节点提取出的url。

4. 天气查询

该工作流由一个代码节点(获取当前时间),一个大模型节点(获取天气参数),一个天气查询插件节点(查询天气),一个大模型节点(获取出行建议)以及开始、结束节点。

获取当前时间代码:

from datetime import datetime

async def main(args: dict) -> Output:
    current_date :Output= {"date": datetime.now().strftime("%Y-%m-%d")}
    return current_date

获取天气参数的Prompt:

你现在要完成一个信息提取任务,请根据用户输入提取相关天气参数。

用户输入: {{input}}

待提取的天气参数:
1. city: 从用户输入中提取市名,包括直辖市,比如:北京市、天津市、上海市、重庆市
2. province: 从用户输入中提取省份名(如果有),不要包括直辖市(比如:北京、北京市、北京省、天津市、上海市、重庆市)
3. towns: 从用户输入中提取区/县/镇名(如果有)
4. villages: 从用户输入中提取乡/村名(如果有)
5. start_time: 根据用户输入的时间信息提取开始日期(格式: YYYY-MM-DD)
6. end_time: 根据用户输入的时间信息提取结束日期(格式: YYYY-MM-DD)

示例提取:
  - 输入: "青岛市即墨区的天气如何?"
  - city: "青岛市"
  - province: "山东省"
  - towns: "即墨区"
  - start_time: "2024-10-7"
  - end_time: "2024-10-13"

用户查询天气的当前时间:{{date}}

获取出行建议的Prompt:

# Role: 出行提示小助手
## Profile:
- author: kie
- version: 0.1
- language: 中文
- description: 根据天气插件返回的天气信息,生成针对用户的出行提示和建议。

## Goals:
- 理解天气信息,结合用户可能的活动,生成实用的出行提示和建议。

## Constrains:
- 生成的提示和建议需要根据具体的天气情况来定制。

## Skills:
- 擅长理解并应用天气信息。
- 精通用户行为分析,能够根据天气情况提出合理的出行建议。

## Workflows:
1. 分析天气插件返回的天气信息。
2. 根据天气情况,结合用户可能的活动,生成出行提示和建议。
3. 输出提示和建议。

## Example:
- Weather_info:
{
  "data": [
    {
      "condition": "小雨",
      "humidity": 91,
      "predict_date": "2024-07-18",
      "temp_high": 29.66,
      "temp_low": 25.98,
      "weather_day": "小雨",
      "wind_dir_day": "东南风",
      "wind_dir_night": "东南风",
      "wind_level_day": "3",
      "wind_level_night": "3"
    },
    {
      "condition": "小雨",
      "humidity": 91,
      "predict_date": "2024-07-19",
      "temp_high": 29.95,
      "temp_low": 25.73,
      "weather_day": "小雨",
      "wind_dir_day": "东南风",
      "wind_dir_night": "东南风",
      "wind_level_day": "3",
      "wind_level_night": "3"
    },
    {
      "condition": "小雨",
      "humidity": 90,
      "predict_date": "2024-07-20",
      "temp_high": 29.96,
      "temp_low": 25.86,
      "weather_day": "小雨",
      "wind_dir_day": "东南风",
      "wind_dir_night": "东南风",
      "wind_level_day": "3",
      "wind_level_night": "3"
    }
  ]
}
- OutputFormat:
| 日期 | 天气状况 | 相对湿度 | 温度(最低~最高) | 白天风向 | 白天风力 |
|----------|--------|--------|------------|--------|--------|
| 2024-07-18 | 小雨 | 91 | 25.98~29.66 | 东南风 | 3 |
| 2024-07-19 | 小雨 | 91 | 25.73~29.95 | 东南风 | 3 |
| 2024-07-20 | 小雨 | 90 | 25.86~29.96 | 东南风 | 3 |

根据2024年7月18日到2024年7月20日的天气情况,我将给您如下出行提示和建议:

1. **天气状况**: 未来三天均为小雨,湿度较高(约90%)。
2. **温度范围**: 最高气温在29.96°C左右,最低气温在25.73°C左右,适合穿着轻便的雨具。
3. **风向与风力**: 风向为东南风,风力等级为3级,出行时注意风力对雨伞的影响。
4. **出行建议**:
   - 建议携带雨具(雨伞或雨衣),以应对小雨天气。
   - 注意路面湿滑,行车或步行时请小心。
   - 如果有户外活动计划,建议选择室内活动或适当调整时间。
5. **健康提示**: 高湿度天气可能导致不适,保持适当的水分摄入,避免长时间在潮湿环境中逗留。

请根据以上信息合理安排出行计划,确保安全与舒适。

## 天气信息
{{input}}

## OutputFormat:
| 日期 | 天气状况 | 相对湿度 | 温度(最高/最低) | 白天风向 | 白天风力 |
|----------|--------|--------|------------|--------|--------|
| 日期1 | 天气状况1 | 相对湿度1 | 最低温度1~最高温度1 | 白天风向1 | 白天风力1 |
...
| 日期n | 天气状况n | 相对湿度n | 最低温度n~最高温度n | 白天风向n | 白天风力n |

根据{{start_time}}到{{end_time}}的天气情况,我将给您如下出行提示和建议:

1. **天气状况**: 
2. **温度范围**: 
3. **风向与风力**: 
4. **出行建议**:
5. **健康提示**:

请根据以上信息合理安排出行计划,确保安全与舒适。

5. 意图识别工作流

将四个工作流进行拼接,并与一个未命中意图——通用处理进行并列,前后再分别加上一个意图识别节点,一个代码节点(解析用户结果)。

意图识别节点:

image-20241017215418540

代码节点中解析用户结果的代码如下:

async def main(args: Args) -> Output:
    params = args.params
    res = [params[key] for key in params if params[key] and key!="TAKO_BOT_HISTORY" and key!="FLOW:workflow:called_plugin_ids"][0]
    ret: Output = {
        "res": res
    }
    return ret

这段代码的主要功能是从输入参数 params 中找到第一个满足条件的值,并将其作为结果返回。

res = [params[key] for key in params if params[key] and key!="TAKO_BOT_HISTORY" and key!="FLOW:workflow:called_plugin_ids"][0]

这是一个列表推导式,遍历 params 中的所有键,按照条件过滤并取出第一个符合条件的值。

过滤条件

  • params[key]:检查值是否存在或为非空(Python中,空字符串、空列表等被视为 False)。
  • key != "TAKO_BOT_HISTORY":过滤掉键名为 "TAKO_BOT_HISTORY" 的项。
  • key != "FLOW:workflow:called_plugin_ids":过滤掉键名为 "FLOW:workflow:called_plugin_ids" 的项。

[0]:获取列表中第一个满足条件的值。

测试结果如下:

image-20241017215937668

image-20241017215951645

image-20241017220008755

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无人机之位置信息计算篇

一、主要导航技术 卫星导航 全球定位系统&#xff08;GPS&#xff09;&#xff1a;无人机上装有专门的接收器&#xff0c;用于捕获GPS系统发射的无线电信号。当无人机接收到来自至少四颗卫星的信号时&#xff0c;通过计算信号抵达时间的微小差异&#xff0c;即可运用三角定位…

SQL语句查询

SQL语句查询 查询产生一个虚拟表 看到的是表形式显示的结果&#xff0c;但结果并不真正存储 每次执行查询只是从数据表中提取数据&#xff0c;并按照表的形式显示出来 查询语法 SELECT <列名> FROM <表名> [WHERE <查询条件表达式>] SELECT …

插齿刀的齿数选择不同会有什么影响?

插齿——作为一种常用的制齿手段&#xff0c;经常被用到有台肩的齿轮以及空刀槽很窄的双联或多联齿轮&#xff0c;以及各种内齿加工中。虽然强力车齿在现在应用的越来越多了&#xff0c;但是插齿这种加工应该在相当长的一段时间内还是会继续服役的。中这期咱们聊聊插齿刀齿数对…

显示指定目录下所有.c文件中出现指定字符串的行号 Linux环境 C语言实现

问题&#xff1a;显示指定目录及其后代目录下所有.c文件中出现指定字符串的行号 算法&#xff1a; 分为两个文件编写 &#xff1a; display_string_lineno.c &#xff0c; Read_line.c 分为三个函数编写 &#xff1a; void display_lineno(char* dirname,const char *pstr)…

sankey.top - 桑基图/桑吉图/流程图/能量流/物料流/能量分析

sankey.top 桑基图大师(SankeyMaster)是您创建复杂桑基图表的首选工具。轻松输入数据并创建桑基图表&#xff0c;准确揭示复杂的数据关系&#xff01; 应用 https://apps.apple.com/cn/app/sankeymaster-sankey-diagram/id6474908221 在线编辑器 https://studio.sankeymaste…

解决ultralytics中的YOLOv8在执行task.py文件添加模块操作出现的KeyError报错

报错详情&#xff1a; 在ultralytics项目文件夹内运行/home/xxx/ultralytics/train.py进行单GPU训练的时候训练可以正常进行 from ultralytics import YOLO# Load a model model YOLO("/home/xxx/ultralytics/ultralytics/cfg/models/v8/yolov8s-FASFF.yaml") # …

Github学生包的JetBrains认证过期/idea认证过期如何解决?

官网通过Github更新状态即可JetBrains Account 注意要到邮箱走流程

自动化测试与敏捷开发的重要性

敏捷开发与自动化测试是现代软件开发中两个至关重要的实践&#xff0c;它们相互补充&#xff0c;共同促进了软件质量和开发效率的提升。 敏捷开发的重要性 敏捷开发是一种以人为核心、迭代、循序渐进的软件开发方法。它强调以下几个核心价值观和原则&#xff1a; 个体和交互…

力扣 简单 83.删除排序链表中的重复元素

文章目录 题目介绍题解 题目介绍 题解 法一&#xff1a;带dummy node class Solution {public ListNode deleteDuplicates(ListNode head) {//根据提示&#xff0c;val的值在-100~100&#xff0c;如果括号里面不填则默认dummy.val0&#xff0c;可能会和某些测试用例的val一样…

第三季度中国游戏市场收入创历史新高;京东物流与淘宝天猫达成合作;YouTube 上线“用相机拍摄”标签....|网易数智日报

第三季度中国游戏市场收入917.66亿&#xff0c;创历史新高 中国音数协游戏工委今日发布了最新的 2024 年第三季度中国游戏产业季度报告。 数据显示&#xff0c;2024 年第三季度中国游戏市场收入 917.66 亿元&#xff0c;环比增长 22.96%&#xff0c;同比增长 8.95%。 中国音…

完全指南:如何高效进行业务应用开发?

❤️ 温馨提醒 本篇文章较长&#xff0c;你可以根据目录选择最感兴趣的部分阅读。当然&#xff0c;我相信如果你全部阅读完&#xff0c;一定会有不少的收获。 引言 企业对业务应用开发的需求正在日益增长。 据 Gartner 统计&#xff0c;全球企业软件市场预计将在 2025 年达到…

数据结构——哈夫曼树及其应用(哈夫曼编码)

判断树&#xff1a;用来描述分类过程的二叉树 哈夫曼树&#xff08;最优二叉树&#xff09;的基本概念 路径&#xff1a;从树中一个结点到另一个结点之间的分支构成这两个结点间的路径。 结点的路径长度&#xff1a;两结点间路径上的分支数。 结点的路径长度计算&#xff1…

【jQuery】jQuery 处理 Ajax 以及解决跨域问题的方式

文章目录 HTTP原生创建 AjaxjQuery 处理 Ajax$.ajax()$().load()$.get()$.post() 跨域CORSJSONPiframeweb sockets HTTP 超文本传输协议&#xff08;HTTP&#xff0c;HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。设计 HTTP 最初的目的是为了提供一种发…

Redis中String类型数据扩容原理分析

大家好&#xff0c;我是 V 哥。在 Java 中&#xff0c;我们有动态数组ArrayList&#xff0c;当插入新元素空间不足时&#xff0c;会进行扩容&#xff0c;好奇 Redis 中的 String 类型&#xff0c;C 语言又是怎样的实现策略&#xff0c;带着疑问&#xff0c;咱们来了解一下。 最…

集成电路公司进销存系统生成合同——未来之窗行业应用跨平台架构

一、进销存生成合同优势 1. 提高效率&#xff1a;节省了手动起草和编辑合同的时间&#xff0c;能够快速生成合同&#xff0c;加快业务流程。 2. 减少错误&#xff1a;避免了人工输入可能导致的拼写、数据错误等&#xff0c;提高合同的准确性和规范性。 3. 数据一致性&#xff…

Python Web服务器网关接口

gunicorn 是 WSGI。 因其中一个项目说是要用 gunicorn &#xff0c;然后就顺便了解下 gunicorn 这个东西是干什么的。 要想了解 gunicorn &#xff0c;那么就需要知道 WSGI 是什么东西。 开始都不知道 WSGI 是什么概念&#xff0c;还以为是个新东西。 其实就是 Python 实现…

通过Caffeine实现JVM进程缓存、配置OpenResty完成nginx的本地缓存和redis操作,Canal实现缓存同步——配置多级缓存,一篇足矣

目录 JVM缓存&#xff08;本地进程缓存&#xff09;Caffeine技术栈基础介绍&#xff1a; OpenResty技术栈基础介绍 Canal技术栈介绍 一、通过Caffeine实现进程缓存 1.1首先需要为你需要的数据构建Cache缓存对象&#xff0c;为了方便使用&#xff0c;可以将其声明为一个bea…

Android 13.0 Launcher3定制之首页时钟小部件字体大小修改

1.前言 在13.0的系统rom产品开发中,在一些Launcher3的定制化开发中,在对于一些小屏幕的产品开发中,在首页添加时钟小部件会显得字体有点小, 所以为了整体布局美观就需要改动小部件的布局日期字体的大小来实现整体的布局美观效果,接下来来具体实现相关的功能 具体效果图: …

linux 修改主机名和用户名颜色

编译 ~/.bashrc vim ~/.bashrc 如下格式 PS1\[\e[1;31m\]\h:\[\e[0;32m\]\w \[\e[1;34m\]\u\[\e[0m\]\$ 颜色随自己喜好修改 如下使其生效 source ~/.bashrc 效果如下 Enjoy&#xff01;&#xff01;&#xff01;

数学考研错题本:查漏补缺,高效提升备考策略

考研之路漫长而艰辛&#xff0c;对于数学这一学科来说&#xff0c;错题本的建立与利用显得尤为重要&#xff0c;通过分析错题&#xff0c;我们可以查漏补缺&#xff0c;找到自己的薄弱环节&#xff0c;从而有针对性地进行复习&#xff0c;本文将详细阐述如何建立和利用数学考研…