零成本——用Dify打造主动嘘寒问暖的虚拟恋人

环境:dify 14.2 docker版本;

模型:glm-4-flash;

工具:dify-on-wechat,timetask;

一、背景

在上一篇《零成本——用 Dify 打造微信虚拟恋人》中,我们顺利地借助 Dify 与 dify-on-wechat 成功打造出了私人定制版的虚拟恋人,且可通过微信实时在线。然而,其存在一定缺陷,即表现得不够主动积极,仅会在被询问时进行回答。今日,我们将进行进阶玩法,以使虚拟恋人能够积极主动地发起对话。

二、实现思路

Timetask 是一款可在dify-on-wechat上运行的插件,其支持自定义定时任务,包括自定义时间、轮询周期等,且具备动态添加任务、取消任务以及查看任务列表等功能,是一款功能强大的定时任务系统插件。通过“dify-on-wechat”,我们引入“Timetask”插件。凭借“Timetask”插件的能力,能够实现定时触发指定问句或内容,进而实现虚拟恋人主动向我们发起对话。

三、实现步骤

  1. 安装timetask插件:进入dify-on-wechat服务的插件文件夹中,docker环境下在/app/plugins中。

    cd /app/plugins
    git clone https://github.com/haikerapples/timetask.git
    cd timetask
    
  2. 进入timetask文件夹中,按需修改配置文件 config.json,可以不用改,就用默认的;

    {
      #定时任务前缀(以该前缀时,会被定时任务插件捕获)
      "command_prefix": "$time", 
      
      #是否开启debug(会输出日志)
      "debug": false,  
      
      #检测频率(默认1秒一次,注意不建议修改!!如果任务带秒钟,则可能会被跳过)
      "time_check_rate": 1, 
      
      #Excel中迁移任务的时间(默认在凌晨4点将Excel 任务列表sheet 中失效的任务 迁移至 -> 历史任务sheet中)
      "move_historyTask_time": "04:00:00", 
    
      #是否每个任务回复前,均 路由查询一遍是否能被其他插件解释,若会被解释,则使用解释内容回复;否则继续查询是否开启了拓展功能,如果均不可被消费,则最终使用原始内容兜底
      #比如 $time 今天 13:35 搜索股票,到达目标时间,则会将 “搜索股票”的关键词默认路由到其他插件查询一遍,如果可以被其他插件解释,则再会使用使用解释后的内容回复。
      #定时内容可自由设定,比如 “搜索股票”、“$tool 查询天气”,只要你的工程的插件可以解释关键字即可(前面2个内容为示例,是否可以成功取决于你工程是否有识别该关键字的插件)
      "is_open_route_everyReply": true,
      
      #是否开启拓展功能(开启后,会识别项目中已安装的插件,如果命中 extension_function中的前缀,则会将消息路由转发给目标插件)
      "is_open_extension_function": true,
      
      #支持的拓展功能列表(理论上 已安装的插件,均支持路由转发,其他插件可自主配置,参考早报的配置方式)
      "extension_function":
      [
        {
          # 触发词
          "key_word": "早报",
        
          # 路由插件的 指令前缀
          "func_command_prefix":"$tool "
        },
        {
          "key_word": "点歌",
          "func_command_prefix": "$"
        },
        {
          "key_word": "搜索",
          "func_command_prefix": "$tool google "
        },
        {
          # 触发词
          "key_word": "GPT",
          "func_command_prefix": "GPT"
        }
      ]
    }
    
  3. 重点: timetask项目作者已经很久没有维护了,在这个项目代码里有个bug,需要我们手动处理下,不然无法成功使用,打开TimeTaskTool.py文件,第80行和81行需要注释掉:

  4. 定制任务:通过 timetask 的配置文件我们可以看到,timetask 支持用户自定义功能,以实现不同的能力。这里,我们以定时发送天气预报为例,实现每天早上 08:00,虚拟恋人主动向我们发送当日天气预报和穿衣建议。发送的内容我们通过 dify 工作流实现并自动写入数据库中(参考《dify 实现数据自动写入数据库》),然后编写 dify-on-wechat 的天气插件,实现调用数据库中的天气信息,并将天气插件加入 timetask 的配置文件中,实现关键词调用。

    编写天气插件,在/app/plugins中新建文件夹,命名为DifyTools,文件夹中新增文件DifyTools.py,这个插件可以实现当用户问句是“天气日报”时,自动查询数据库中天气预报的内容;

    import os
    import json
    import requests
    from common.log import logger
    import plugins
    from bridge.context import ContextType
    from bridge.reply import Reply, ReplyType
    from plugins import *
    import config
    import mysql.connector  # 导入用于连接MySQL数据库的库
    
    @plugins.register(name="DifyTools",
                      desc="根据不同指令获取对应数据库内容并回复",
                      version="1.0",
                      author="vhql",
                      desire_priority=501)
    class DifyTools(Plugin):
        def __init__(self):
            super().__init__()
            self.handlers[Event.ON_HANDLE_CONTEXT] = self.on_handle_context
            logger.info(f"[{__class__.__name__}] initialized")
    
        def get_help_text(self, **kwargs):
            return "输入“天气日报”获取对应最新天气。"
    
        def on_handle_context(self, e_context):
            if e_context['context'].type == ContextType.TEXT:
                content = e_context["context"].content.strip()
                if content.startswith("天气日报"):
                    logger.info(f"[{__class__.__name__}] 收到消息: {content}")
                    self.fetch_weather_news(e_context)
    
        def fetch_weather_news(self, e_context):
            return self._fetch_news_from_table(e_context, "weather_new_report")
          
        def _fetch_news_from_table(self, e_context, table_name):
            """
            从指定的数据库表中获取最近一条数据,并进行相应处理。
    
            :param e_context: 消息上下文对象,包含回复等相关信息
            :param table_name: 要查询数据的数据库表名
            :return: 无
            """
            db_config = {
                "host": "192.168.3.86",
                "port": "3306",
                "user": "user",
                "password": "password",
                "charset": "utf8",
                "database": "database"
            }
    
            try:
                conn = mysql.connector.connect(**db_config)
                cursor = conn.cursor()
                query = f"SELECT date, text FROM {table_name} ORDER BY date DESC LIMIT 1"
                cursor.execute(query)
                result = cursor.fetchone()
                if result:
                    date, text = result
                    self.construct_reply([{"date": date, "text": text}], e_context)
                else:
                    logger.error(f"未查询到{table_name.split('_')[0]}天气数据")
                    self.send_error_reply(e_context, f"获取{table_name.split('_')[0]}天气失败,暂无数据。")
    
                cursor.close()
                conn.close()
            except Exception as e:
                logger.error(f"数据库操作抛出异常: {e}")
                self.send_error_reply(e_context, f"请求{table_name.split('_')[0]}天气失败,请稍后再试。")
      
        def construct_reply(self, newslist, e_context):
            reply = Reply()
            reply.type = ReplyType.TEXT
    
            content = e_context["context"].content.strip()
            if content.startswith("天气日报"):
                reply_prefix = "📢 天气预报:\n\n"
            else:
                reply_prefix = ""
    
            # 构造回复内容
            reply.content = reply_prefix
            for i, news_item in enumerate(newslist, 1):
                date = news_item.get('date', '未知日期')
                text = news_item.get('text', '').replace("**", "").replace("#", "")
                reply.content += f"⌚️更新时间:{date}\n\n{text}"
    
            e_context["reply"] = reply
            e_context.action = EventAction.BREAK_PASS
      
    
        def send_error_reply(self, e_context, message):
            reply = Reply()
            reply.type = ReplyType.TEXT
            reply.content = message
            e_context["reply"] = reply
            e_context.action = EventAction.BREAK_PASS
    

    新增文件__init__.py

    from .DifyTools import *
    
  5. 重启dify-on-wechat服务,会自动安装timetask和DifyTools插件,和虚拟恋人发送#help timetask可以查看timetask功能介绍。

  6. 和虚拟恋人发送 “$time 每天 06:50:00 天气日报”,以后每天早上虚拟恋人都会主动和你发送当天的天气预报啦!

关注微信公众号【红岸解码室】,发送“天气预报”,获取天气预报DSL文件!

### DeepSeek Knowledge Base and Resources Overview DeepSeek represents a significant advancement in the field of large language models (LLMs). For those interested in exploring resources related to DeepSeek, several avenues are available that can provide comprehensive information on this topic. The GitHub project named “awesome-LLM-resources” offers an extensive collection of LLM-related materials covering various aspects such as data, fine-tuning, inference, evaluation, RAG, Agent, search, books, courses, tutorials, papers, and tips[^2]. This repository serves as a valuable starting point for anyone looking into advanced LLMs like DeepSeek. Although not specifically focused on DeepSeek, it provides broad coverage of relevant topics which may include references or comparisons involving DeepSeek. Additionally, when creating resource stacks using templates similar to what is described under 'Resources' sections within cloud formation documents[^1], one could structure projects around collecting and organizing specific assets pertinent to studying or implementing solutions with DeepSeek technology. For direct access to official documentation or specialized forums dedicated solely to DeepSeek, visiting its primary website or joining community platforms where discussions about cutting-edge AI technologies occur would be beneficial. These sources typically offer up-to-date insights directly from developers working closely with these systems. #### Example Code Snippet Demonstrating Resource Stack Creation ```yaml Resources: MyResourceStack: Type: "AWS::CloudFormation::Stack" Properties: TemplateURL: https://example.com/deepseek-template.yaml Parameters: ProjectName: "DeepSeekProject" ``` --related questions-- 1. What types of datasets are most commonly used for training models like DeepSeek? 2. How does the architecture design of DeepSeek differ from other leading LLMs? 3. Can you recommend any particular tutorial series focusing on practical applications of DeepSeek? 4. Are there any notable research papers discussing advancements made by DeepSeek's development team?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值