零风险!零付费!我把 AI 接入微信群,爸妈玩嗨了~附教程(下):大模型 API 接入

news2024/12/23 2:09:17

上篇,带大家玩转高德开放平台 API,为大模型提供和本地生活相关的可靠信息。

本文将带大家,结合免费的大模型API,基于微信机器人开发框架,打造完整的 Bot。

友情提醒:注册一个小号使用,严禁用于违法用途(如发送广告/群发/诈骗、色情、政治等内容),否则封号是早晚的事哦。

0. 开发框架选择

之前给大家分享过三种微信机器人的搭建方案,要么账号容易被封禁,要么需要付费使用。

有没有零风险,零付费的方案?

有的,本文将基于:搭建微信机器人的第4种方式,免费开源,轻量高效 中的框架进行实现,占用资源不多,而且可定制化程度非常高!

1. 大模型准备

尽管免费的 API 有速率限制,不过对于个人使用而言,完全足够!

前天,给大家盘点了免费且靠谱的大模型 API,统一封装,任性调用,赶紧用起来!

为了在应用中,任意切换各种大模型 API,我这里接入了所有兼容 OpenAI 格式的大模型,并进行统一封装,下面给出示例代码:

from openai import OpenAI
model_dict = {
    'gemini-1.5-pro': {
        'api_key': server_api_key,
        'base_url': server_url,
        'model_name': 'gemini-1.5-pro'
    },
    'ernie-128k': {
        'api_key': server_api_key,
        'base_url': server_url,
        'model_name': 'ERNIE-Speed-128K'
    },
}

class UniLLM:
    def __init__(self):
        model_names = list(model_dict.keys())
        self.models = {name: LLM_API(api_key=model_dict[name]['api_key'], base_url=model_dict[name]['base_url'], model=model_dict[name]['model_name']) for name in model_names}

    def __call__(self, model_name, messages, temperature=0.7):
        model = self.models.get(model_name)
        return model(messages, temperature=temperature)

2. 微信机器人开发

参考:搭建微信机器人的第4种方式,相信看到这里的你,已经把服务部署好了。

首先,进行需求分析:一个完整的 Bot 应该具备哪些功能?

  • 基本功能:
    • 自动发送消息;
    • 自动接收消息并处理。
  • 特色功能:
    • 定时任务;
    • 本地生活服务。

为了快速实现 MVP 版本,这里优先完成以上功能。

来吧,一起一步步把 Bot 搭建好。

2.0 服务部署

参考上篇,采用 docker 一键部署,如果运行过程中遇到问题,可打印最后几行日志查看:

PS:如需更多定制化功能,也可选择源码部署,不过坑略多,下篇跟大家分享。

sudo docker logs --tail 40 wx

如果运行过程中新建了群,需要重启容器:

sudo docker restart wx # 容器名称 or 容器 id 均可

2.1 发送消息接口

这个比较简单,服务部署后就有了,再贴下代码:

def send_message(to='user', content='hello', isRoom=False):
    url = f'http://129.150.39.xxx:3001/webhook/msg/v2?token=123'
    data = {
        "to": to,
        "isRoom": isRoom,
        "data": {"content": content}
    }
    response = requests.post(url, headers={'Content-Type': 'application/json'}, data=json.dumps(data))
    if response.status_code == 200:
        print(response.json())
    else:
        print('发送接口调用失败')

2.2 接收消息接口

接收消息的接口,需要部署一个服务,这里我们选用 FastAPI 搭建。

接口定义如下:

app = FastAPI()

@app.post("/receive")
async def receive_message(request: Request):
    # 处理请求数据
    data = await request.form()
    message_type = data.get("type")
    content = data.get("content")
    source = data.get("source")
    is_from_self = data.get("isMsgFromSelf")
    try:
        # 填写处理逻辑-开始
        handle_message(message_type, content, source, is_from_self)
        # 填写处理逻辑-结束
        return JSONResponse(content={"status": True, "data": {"type": "text", "content": "success"}})
    except Exception as e:
        return JSONResponse(content={"status": False, "data": {"type": "text", "content": "failed"}})
        
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=3000)

注意:上述接口需指定返回值,否则报错。

接下来,我们需要接收消息后的处理逻辑:

def handle_message(message_type='text', content='', source='', is_from_self="0"):
    # 初版只处理文本
    if message_type != "text":
        return
    source = json.loads(source)
    from_name = source['from']['payload']['name']
    if source['room']:
        if '@小爱' not in content: # 群聊中非@消息
            return
        content = content.replace("@小爱", "")
    # 处理逻辑-content
    bot_answer = get_bot_answer(content)
    if source['room']:
        bot_answer = f'@{from_name} {bot_answer}'
        send_message(to=source['room']['payload']['topic'], content=bot_answer, isRoom=True)
    else:
        send_message(to=from_name, content=bot_answer, isRoom=False)
    return bot_answer

具体回复什么内容,封装在 get_bot_answer() 函数中,下面我们就来搞定它!

2.3 本地生活服务

上一篇中,我们已经搭建好了利用高德开放平台提供的本地生活服务API

为了能够让 LLM 认识它们,并且合理调用他们,我拆解成了三个步骤:

  1. 首先,根据用户输入,判断用户意图;
  2. 然后,根据意图调用相应的API接口,获取可靠的本地生活信息;
  3. 最后,基于API返回的信息,LLM 整理后,回复用户。

我们一步步来搞定它!

2.3.1 意图识别

我这里预先定义了 6 种意图:['天气', '步行规划', '骑行规划', '驾车规划', '公交规划', '地点推荐'],如果识别结果不在意图列表中,则直接调用 LLM 进行回答。

# 1. 首先判断意图
intention = intention_rec(user_content)
print(f'意图识别结果:{intention}')
if intention not in intentions_list:
    messages = [
        {'role': 'system', 'content': sys_base_prompt},
        {'role': 'user', 'content': user_content}
    ]
    res = unillm(model_name=model_name, messages=messages)
    return res.strip() if res else f'小爱有点累了,稍候再试吧'

给大家展示下意图识别的日志:

2.3.2 调用本地生活接口

接下来,根据意图识别结果调用对应的本地生活接口,下面以天气预报为例:

首先需要LLM 提取出用户输入中的地址信息;

然后请求天气预报接口get_weather获取天气;

最后 LLM 进行整理,返回给用户。

# 2. 根据意图进行相应的操作
## 2.1 天气预报
if intention == '天气':
    # 提取地址
    messages = [{'role': 'user', 'content': f'{user_content},提取这句话中的地址信息,只需回答地址'},]
    res_address = unillm(model_name='glm4-9b', messages=messages)
    res_address = res_address.strip()
    wea_cast = get_weather(res_address, extensions='all')
    if not wea_cast:
        return '未找到该地址的天气信息,建议地址信息:省/市/区/'
    forecasts = wea_cast['forecasts'][0]['casts']
    today_cast = json.dumps(forecasts[0], ensure_ascii=False)
    future_cast = json.dumps(forecasts[1:], ensure_ascii=False)
    # 调用 LLM
    messages = [
        {'role': 'system', 'content': sys_weather_report},
        {'role': 'user', 'content': f'地名:{res_address};今日天气:{today_cast};未来三天:{future_cast};用户问题:{user_content}'},
    ]
    res_weather = unillm(model_name=wea_model_name, messages=messages)
    return res_weather if res_weather else f'小爱有点累了,稍候再试吧'

2.3.3 效果对比

比如我问他:周末不知道干点啥好

下面是没有意图识别的结果:

收不住啊,胡诌了个鲤中步行街给我,这是什么地方?

接下来是意图识别的结果(地点推荐):基于高德的检索信息,LLM 给我答复如下。

2.4 定时任务实现

我们简单实现两个定时任务:

  • 每天播报指定地区的天气信息;
  • 根据成员的生日日期,自动发送生日祝福。

如果你的服务部署在海外,强烈建议为服务器设置时区:

# 查看当前时区
timedatectl
# 设置
sudo timedatectl set-timezone Asia/Shanghai
# 验证
timedatectl

执行后,就不用像上篇那样在代码中指定时区了。

2.4.1 每日天气播报

指定要发送的群聊名称,和要播报的地区:

def send_weather(to='机器人测试', addresses=['上海杨浦区',]):
    for add in addresses:
        content = weather_forecast(add)
        send_message(to=to, isRoom=True, content=content.strip())

2.4.2 定期生日祝福

首先定义一个字典,用于存放群成员的生日信息:

birthday_dict = {
    '爸爸': '07-25',
    '大哥': '07-25',
    '二哥': '07-25',
    '妈妈': '07-25',
    '大姐': '07-25',
}

考虑到国内大部分小伙伴,常用阴历生日,这里可以设置一下阳历/阴历转换:

from lunarcalendar import Converter, Solar, Lunar
# 阴历转换为阳历
def lunar_to_solar(date, leap_month=False):
    year, month, day = date.split('-')
    lunar_date = Lunar(int(year), int(month), int(day), leap_month)
    solar_date = Converter.Lunar2Solar(lunar_date)
    date = f'{solar_date.year}-{solar_date.month:02d}-{solar_date.day:02d}'
    return date

每天定时遍历,如果今天有某位群成员的生日,则调用 LLM 发送生日祝福:

def send_birthday_wish(to='机器人测试'):
    today = str(datetime.now().date())
    today_lunar = solar_to_lunar(today)
    today_lunar = '-'.join(today_lunar.split('-')[1:])
    if today_lunar in birthday_dict.values():
        for name, birthday in birthday_dict.items():
            if birthday == today_lunar:
                content = birthday_wish(name, solar=today, lunar=today_lunar)
                send_message(to=to, isRoom=True, content=content.strip())

最后,把所有定时任务放到后台去跑吧:

if __name__ == '__main__':
    # 每天发送天气预报
    group_name = 'xxx'
    schedule.every().day.at("06:30").do(lambda: send_weather(to=group_name))
    # 设置生日祝福任务
    schedule.every().day.at("06:00").do(lambda: send_birthday_wish(to=group_name))
    while True:
        schedule.run_pending()
        time.sleep(1)

给大家看下测试效果:

还不知道怎么给家人发生日祝福?问问小爱吧~

写在最后

汇集各路大模型 API,以及高德提供的本地生活接口,终于把一个简单的微信机器人捏完了。

项目还在迭代中,大家有更好的想法,欢迎评论区交流。

如果本文对你有帮助,不妨点个免费的赞收藏备用。


为了方便大家交流,新建了一个 AI 交流群,欢迎感兴趣的小伙伴加入。

小爱也在群里,想进群体验的朋友,公众号后台「联系我」即可,拉你进群。

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

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

相关文章

数组和指针 笔试题(3)

目录 11.笔试题11 12.笔试题12 13.笔试题13 14.笔试题14 11.笔试题11 //笔试题11(难)int a[5][5];//创建25个int类//p[]1[]2[]3[]4[]5 []6[]7[]8[]9[]10 []11[]12[]13[]14[]15 []16(p[4])[][](p[4][2])[][] [][]&a…

如何使用“在页面上查找?

如何使用“在页面上查找? 按 CTRL F ,然后输入要搜索的单词或短语。

如何在Pyqt中渲染使用svggraphicsItem的SVG字形?

在使用 PyQt 构建应用程序时,有时需要在图形用户界面中渲染 SVG(可缩放矢量图形)文件,特别是当你需要显示图标或自定义字体时。QGraphicsSvgItem 是 PyQt 提供的一个类,用于在 QGraphicsView 或 QGraphicsScene 中渲染…

Python数据分析实战,兰州市二手房市场深度分析

作为购房者,除了关注地段与价格外,房屋的总价与面积的关系,以及房屋朝向的选择,同样是决策过程中的关键因素。那么,兰州市的二手房市场中,房屋总价与面积之间究竟存在怎样的关系?各个朝向的房源…

【人工智能】AI时代是失业的噩梦,还是效率的提升?

我们都知道,人工智能(AI)正以前所未有的速度渗透到我们生活的方方面面。有人说,AI的发展将导致大部分人失业。然而,另一部分人则认为,AI是提升工作效率的利器。那么,真相究竟是什么呢&#xff1…

怎样在公司将手机屏幕(远程)投屏到家里的大电视上?

我不住家里,前几次回去都会替老爸老妈清理手机。这两个星期没空回去,老爸吐槽手机用几天就又卡了,其实就是清理一些手机缓存的问题。 我说我远程控制他的手机,给他清理一下。他一听“控制”就不喜欢,说我大了&#xf…

年薪80万,成功入职字节跳动!

前言: 最近AI相关就业岗位爆了。。。无论是**华为、**百度、阿里、字节等互联网巨头,还是中小型的科技公司都在高薪挖 AI 人才。 上周找 字节的面试官朋友(职级3-1)要来了几套高质量AI****内部资料和2024吴恩达机器学习资料。既…

Linux_kernel汇编指令05

一、温故知新 1、跳转指令 b{cond} <target_label> 相当于C语言中的goto <target_label>是跳转地址&#xff0c;32M {cond}是条件码&#xff0c;先决条件 根据CPSR寄存器的NZCV位来决定是跳转还是不跳转 bl l&#xff1a;带链接状态&#xff0c;将PC寄存器的值保存…

浅谈人工智能之VSCode:使用插件与ollama本地大模型交互

浅谈人工智能之VSCode&#xff1a;使用插件与ollama本地大模型交互 我们在之前的文档中已经说明如何使用Ollama部署本地大模型&#xff0c;这里就赘述&#xff0c;具体如何部署可参考文档&#xff1a; 浅谈人工智能之Windows&#xff1a;基于ollama进行本地化大模型部署 准备…

CDKF(中心差分卡尔曼滤波)的MATLAB代码(附下载链接)

文章目录 CDKF介绍运行结果代码下载链接部分代码如下 CDKF介绍 另有关于EKF和CDKF的对比程序&#xff1a;EKFCDKF两个滤波的MATLAB程序&#xff0c;估计三轴位置&#xff0c;带中文注释——https://blog.csdn.net/callmeup/article/details/136610153。此文章所在的专栏还有更…

传统CV算法——基于Opencv的图像绘制

直线绘制 参数解析&#xff1a; &#xff08;图像矩阵&#xff0c;直线起始坐标&#xff0c; 直线终止坐标、颜色、线条厚度&#xff09; cv2.line()是OpenCV中用于绘制直线的函数。 参数说明&#xff1a;img&#xff1a;要绘制直线的图像矩阵。(100,30)&#xff1a;直线的起…

移动端支持风格设计,更个性化的体验

08/28 主要更新模块概览 风格设计 风格配置 列表模式 跳转按钮 01 表单管理 1.1 【表单设计】-新增移动端风格设计 说明&#xff1a; 在此之前&#xff0c;移动端风格一直继承自 PC 端风格&#xff0c;无法进行自定义。…

Ollama拉起本地模型以及rag系统部署。

什么是 Ollama &#xff1f; Ollama 是一个简明易用的本地大模型运行框架。能在本地启动并运行 Llama、qwen、Gemma 及其他大语言模型&#xff0c;没有GPU资源照样可以拉起模型&#xff0c;和LocalAI 比较类似&#xff0c;但是加载模型更容易。 1.安装 安装后运行&#xff0c…

带你0到1之QT编程:四、打地基QHash的高效用法

此为QT编程的第四谈&#xff01;关注我&#xff0c;带你快速学习QT编程的学习路线&#xff01; 每一篇的技术点都是很很重要&#xff01;很重要&#xff01;很重要&#xff01;但不冗余&#xff01; 我们通常采取总-分-总和生活化的讲解方式来阐述一个知识点&#xff01; 码…

安泰功率放大器应用领域:铁电材料极化测试

铁电材料是一种非常重要的电介质材料&#xff0c;不仅具有较高的介电常数&#xff0c;还有显著的热释电效应和压电效应&#xff0c;因此也被广泛应用于从日常生活到高端技术的多个领域。功率放大器作为铁电材料极化测试中常用的测试仪器之一&#xff0c;在该领域也有着良好应用…

【系统方案】网络空间安全态势感知与大数据分析平台建设方案(Doc完整版)

1.1 网络空间态势感知系统系统建设 1.1.1 安全监测子系统 1.1.2 态势感知子系统 1.1.3 通报预警子系统 1.1.4 等保管理子系统 1.1.5 追踪溯源子系统 1.1.6 威胁情报子系统 1.1.7 指挥调度子系统 1.1.8 侦查调查子系统 1.1.9 应急处置子系统 1.1.10 移动APP 1.1.11 运…

html发送邮件的服务器怎么配置?如何设置?

html发送邮件如何保障安全性&#xff1f;HTML发送邮件链接方法&#xff1f; 配置一个能够高效处理html发送邮件的服务器&#xff0c;不仅可以提升邮件的美观性和互动性&#xff0c;还能增强邮件的专业度和吸引力。AokSend将详细介绍如何配置服务器以支持html发送邮件。 html发…

Aigtek功率放大器的基本要求是什么

功率放大器是电子电路中的关键元件&#xff0c;用于增加输入信号的幅度&#xff0c;以便有效地驱动负载。为了确保功率放大器在不同应用中能够可靠地工作&#xff0c;需要满足一系列基本要求。下面安泰电子将详细介绍功率放大器的基本要求&#xff0c;以帮助读者了解其设计和应…

echarts关系图报错Graph nodes have duplicate name or id

生成的关系图&#xff0c;数据有了&#xff0c;展示报错nodes have duplicate name or id&#xff0c;提示节点有重复的名称或id&#xff0c;意思是可能有重复的节点&#xff0c;echarts graph 它不支持所以报错了。如下图 有几百条数据&#xff0c;要找到那条重复的&#xff…

kubernetes集群部署Confluence 7.2.0+mysql 5.7(自测有效)

背景介绍&#xff1a; Confluence是一个专业的企业知识管理与协同软件。使用简单&#xff0c;但它强大的编辑和站点管理特征能够帮助团队成员之间共享信息、文档协作、集体讨论&#xff0c;信息推送。 这里介绍的使用的是Confluence 7.2.0版本的。 一、在kubernetes集群部署 1…