群里的AI机器人
大家好,我是石小石
!
今天在某群潜水,突然被一段对话吸引了。
很明显,这个【前端汤姆猫】是一个AI,我也来逗逗他
然而,我的弱智吧问题还没来得及问,可怜的机器人就被管理同学关进小黑屋了,不过瘾啊! 不过,作为一个程序员,对AI机器人的实现,我非常感兴趣。
简单搜索后,我发现AI机器人的实现非常简单,那我也手搓一个玩玩吧。
机器人原理与实现技术方案
原理
如今,AI模型的发展已经非常成熟,我们很容易就能想到AI机器人的原理
- 用户在微信群中发送消息。
- 机器人监听到消息后,将其转发到 AI 模型进行处理。
- 模型返回生成的内容,机器人再发送回群聊。
刚好,前几天用了一个免费的AI大模型搭建了一个私有的聊天机器人。
文章链接:node+websoket极速构建一个私有ChatGPT!AI套壳居然如此简单!
文章中实现的效果展示:
看来,现在我只需要把它改造改造,接入微信就行了!
技术方案
搭建一个基础的AI机器人,我们会用到下面两个东西
- GPT 系列语言模型,负责生成智能回答。
- Node.js:搭建服务端逻辑(java、python什么的都可)。
在之前的文章中,我也介绍过,AI大模型有很多,国产的如豆包、文心一言、通义千问、kimi 等。考虑到免费、SDK调用简单等因素,本文我们使用Kimi的月之暗Moonshot模型。
如果需要将搭建的AI机器人接入微信,我们还需要使用Wechaty和qrcode-terminal。
Wechaty是一个开源的 Node.js 库,用于操作微信,提供登录、接收消息、发送消息等功能。它是我们实现微信AI机器人的核心,它的官网有非常详细的使用介绍
qrcode-terminal是一个非常简单的插件,它的作用是在终端打印二维码,用于扫描登录微信。
实现目标
通过以上技术栈,我们将从0到1搭建一个微信群 AI 聊天机器人,它具备以下功能:
- 基础功能:使用 Wechaty 登录微信并监听群聊消息,当群成员@机器人时触发智能回复。
- 智能化回复:通过上下文记忆提供连续对话,借助KImi月之暗模型进行回复。
- 个性化与趣味化:预设机器人角色(如“
闷骚的程序员
”),提升对话趣味性,并通过自定义触发词和消息过滤优化使用体验。
最终我们将实现一个既智能又人性化、具有实用性的微信 AI 机器人。
代码实现
准备开发环境
我们服务端使用nodejs,因此,首先确保安装 Node.js (推荐 v14 或更高版本)环境。
创建项目并初始化:
mkdir ai-chatbot && cd ai-chatbot
npm init -y
安装依赖:
npm install wechaty qrcode-terminal axios
登录微信
扫码登录是实现微信聊天机器人的第一步,我们需要通过wechaty qrcode-terminal
两个插件在服务端实现微信登录,只有这样,我们才能实现调试开发。
通过wechaty,我们只需要6行代码,就可以 通过个人号 搭建一个 微信机器人功能 ,用来自动管理微信消息,它的核心代码如下
注:为避免官方封号,建议大家用小号!由于您自己操作导致的封号,本文概不负责!
import { Wechaty } from 'wechaty'
Wechaty.instance()
.on('scan', qrcode => console.log('扫码登录:' + qrcode))
.on('login', user => console.log('登录成功:' + user))
.on('message', message => console.log('收到消息:' + message))
.on('friendship', friendship => console.log('收到好友请求:' + friendship))
.on('room-invite', invitation => console.log('收到入群邀请:' + invitation))
.start()
我们在项目根目录创建index.js,写一个最基础的登录代码。
const { WechatyBuilder, ScanStatus, log } = require("wechaty");
const qrcodeTerminal = require("qrcode-terminal");
// 创建 Wechaty 实例
const bot = WechatyBuilder.build({ name: "chatanywhere-bot" });
// 处理扫码事件
bot.on("scan", (qrcode, status) => {
if (status === ScanStatus.Waiting || status === ScanStatus.Timeout) {
qrcodeTerminal.generate(qrcode, { small: true });
console.log(
`扫码链接:https://wechaty.js.org/qrcode/${encodeURIComponent(qrcode)}`
);
} else {
log.info("扫码状态:", status);
}
});
// 登录与登出事件
bot.on("login", (user) => console.log(`登录成功:${user.name()}`));
bot.on("logout", (user) => console.log(`已登出:${user.name()}`));
// 启动机器人
bot.start().catch((e) => console.error(e));
上面的代码实现了二维码生成、二维码扫描、扫码后登录状态的监控等功能,在控制台输入node index.js运行代码,我们就能看到一个微信二维码。
用微信扫描后,你就可以看到手机端的登录提示
实际上,这个二维码是一个用于登录微信网页版的二维码,但是,现在用网页登录不上了。
这意味着,想接入微信手机版或pad,你需要购买一个token或申请使用。为了便于演示核心,本文不会教你如何购买token和配置,请参考官方教程
监听群聊消息
扫码成功后,我们可以继续实现监听群聊消息的功能
// 监听消息事件
bot.on('message', async (msg) => {
const talker = msg.talker(); // 消息发送者
const text = msg.text(); // 消息内容
const room = msg.room(); // 群聊信息
if (room) {
const topic = await room.topic(); // 获取群名称
console.log(`[群聊: ${topic}] ${talker.name()}: ${text}`);
} else {
console.log(`[私聊] ${talker.name()}: ${text}`);
}
});
引入 Kimi AI大模型
要让机器人智能回复,我们需要借助 Kimi的月之暗 模型。具体的使用方法参考我之前的文章:juejin.cn/post/744177…
import axios from 'axios';
const OpenAI = require("openai");
// 配置 Moonshot AI 客户端
const client = new OpenAI({
apiKey: "你自己在kimi后台创建的API key",
baseURL: "https://api.moonshot.cn/v1", // Moonshot API 的基础路径
});
async function getAIResponse(message) {
try {
const response = await client.chat.completions.create({
model: "moonshot-v1-8k",
messages: [
{ role: "user", content },
],
temperature: 0.3, // 控制回答的随机性
});
// 3.获取 Kimi 的回答内容
const reply = completion.choices[0]?.message?.content
// 4.将回答返回
return reply;
} catch (error) {
console.error('AI Error:', error);
return '抱歉,我的大脑短路了,请稍后再试!';
}
}
上述代码中,我们定义了一个getAIResponse
的方法,这个方法会根据message的参数值(其他用户的消息)调用Kimi的模型接口,返回AI回答。
智能回复群聊消息
现在,我们需要将AI回答通过Wechaty返回微信,并将返回结果发送到群聊。
bot.on('message', async (msg) => {
const room = msg.room(); // 获取群聊
const text = msg.text(); // 消息内容
// 忽略自己的消息
if (msg.self()) return;
// 如果在群聊中,且 @ 了机器人
if (room && text.includes(`@${bot.name()}`)) {
const cleanText = text.replace(`@${bot.name()}`, '').trim(); // 去除 @ 内容
const reply = await getAIResponse(cleanText); // 调用 GPT 接口
await room.say(reply, msg.talker()); // 回复消息
}
});
上述代码并不复杂,基本都是在调官方的api而已。
优化机器人
上下文记忆
为了让我们的AI机器人更加智能,我们需要保存最近几条消息,模拟连续对话。
const axios = require("axios");
const OpenAI = require("openai");
// 配置 Moonshot AI 客户端
const client = new OpenAI({
apiKey: "你自己在kimi后台创建的API key", // 替换为你的API密钥
baseURL: "https://api.moonshot.cn/v1", // Moonshot API 的基础路径
});
// 会话管理对象,存储每个用户的对话历史
const sessions = {};
async function getAIResponse(sessionId, message) {
try {
// 如果该会话还没有历史记录,初始化它
if (!sessions[sessionId]) {
sessions[sessionId] = [];
}
// 将用户消息添加到历史记录
const userMessage = { role: "user", content: message };
sessions[sessionId].push(userMessage);
// 调用 Moonshot API 获取 AI 回复
const response = await client.chat.completions.create({
model: "moonshot-v1-8k", // 使用你选择的模型
messages: sessions[sessionId], // 传递完整的对话历史
temperature: 0.3, // 控制回答的随机性
});
// 获取 AI 回复内容
const assistantMessage = response.choices[0]?.message?.content || "抱歉,我无法回答您的问题。";
sessions[sessionId].push({ role: "assistant", content: assistantMessage }); // 记录 AI 回复
// 返回 AI 回复
return assistantMessage;
} catch (error) {
console.error("AI Error:", error);
return "抱歉,我的大脑短路了,请稍后再试!";
}
}
// 监听消息事件
bot.on('message', async (msg) => {
const room = msg.room(); // 获取群聊
const text = msg.text(); // 消息内容
// 忽略自己的消息
if (msg.self()) return;
// 如果在群聊中,且 @ 了机器人
if (room && text.includes(`@${bot.name()}`)) {
const cleanText = text.replace(`@${bot.name()}`, '').trim(); // 去除 @ 内容
const sessionId = msg.talker().id; // 使用 talker 的 ID 来唯一标识会话
const reply = await getAIResponse(sessionId, cleanText); // 调用 AI 接口并获取回答
await room.say(reply, msg.talker()); // 回复消息
}
});
代码中的注释已经非常详细了,这里我就不过多赘述了!
定制化AI人设
为了让 AI 拥有预设性格,我们可以在每次回答问题时,传入一个固定的系统提示。
// ...
// 预设性格:程序员
const systemMessage = {
role: "system",
content:
"你是一个闷骚的程序员,热爱开发!对别人的回复要充满对代码开发的激情!",
};
async function getAIResponse(sessionId, message) {
try {
// 如果该会话还没有历史记录,初始化它
if (!sessions[sessionId]) {
sessions[sessionId] = [];
}
// 在每个会话开始时加上系统消息来设定机器人的性格
sessions[sessionId] = [systemMessage, ...sessions[sessionId]];
// ...
} catch (error) {
// ...
}
}
// 监听消息事件
bot.on('message', async (msg) => {
// ...
});
当然,你的固定提示可以有很多,只需要将systemMessage变成一个数组即可。
更加精细化的操作,可以参考kimi的官方文档。
自动加好友
bot.on('friendship', async (friendship) => {
if (friendship.type() === 2) {
await friendship.accept(); // 自动接受好友请求
}
});
上面的代码是官方的demo写法,也没什么可说的
其他功能
除了上述的基本功能外,wechaty还提供了更多的微信操作功能,我们可以借助官方的示例,实现更多的功能。
大家可以根据需求自行添加代码。
完整代码
const { WechatyBuilder, ScanStatus, log } = require("wechaty");
const qrcodeTerminal = require("qrcode-terminal");
const axios = require("axios");
const OpenAI = require("openai")
;
// 创建机器人实例
const bot = WechatyBuilder.build({
name: 'ai-chatbot', // 定义机器人名字
});
// 配置 Moonshot AI 客户端
const client = new OpenAI({
apiKey: "你自己在kimi后台创建的API key", // 替换为你的API密钥
baseURL: "https://api.moonshot.cn/v1", // Moonshot API 的基础路径
});
// 会话管理对象,存储每个用户的对话历史
const sessions = {};
// 预设性格:程序员
const systemMessage = {
role: "system",
content:
"你是一个闷骚的程序员,热爱开发!对别人的回复要充满对代码开发的激情!",
};
// 监听扫码事件
bot.on('scan', (qrcode, status) => {
if (status === ScanStatus.Waiting || status === ScanStatus.Timeout) {
const qrcodeImageUrl = `https://wechaty.js.org/qrcode/${encodeURIComponent(qrcode)}`;
log.info('AI Chatbot', `Scan QR Code to login: ${qrcodeImageUrl}`);
qrcodeTerminal.generate(qrcode, { small: true }); // 在终端打印二维码
}
});
// 调用 Moonshot API 获取 AI 回复
async function getAIResponse(sessionId, message) {
try {
// 如果该会话还没有历史记录,初始化它
if (!sessions[sessionId]) {
sessions[sessionId] = [];
}
// 在每个会话开始时加上系统消息来设定机器人的性格
sessions[sessionId] = [systemMessage, ...sessions[sessionId]];
// 将用户消息添加到历史记录
const userMessage = { role: "user", content: message };
sessions[sessionId].push(userMessage);
// 调用 Moonshot API 获取 AI 回复
const response = await client.chat.completions.create({
model: "moonshot-v1-8k", // 使用你选择的模型
messages: sessions[sessionId], // 传递完整的对话历史
temperature: 0.3, // 控制回答的随机性
});
// 获取 AI 回复内容
const assistantMessage = response.choices[0]?.message?.content || "抱歉,我无法回答您的问题。";
sessions[sessionId].push({ role: "assistant", content: assistantMessage }); // 记录 AI 回复
// 返回 AI 回复
return assistantMessage;
} catch (error) {
console.error("AI Error:", error);
return "抱歉,我的大脑短路了,请稍后再试!";
}
}
// 监听消息事件
bot.on('message', async (msg) => {
const room = msg.room(); // 获取群聊
const text = msg.text(); // 消息内容
// 忽略自己的消息
if (msg.self()) return;
// 如果在群聊中,且 @ 了机器人
if (room && text.includes(`@${bot.name()}`)) {
const cleanText = text.replace(`@${bot.name()}`, '').trim(); // 去除 @ 内容
const sessionId = msg.talker().id; // 使用 talker 的 ID 来唯一标识会话
const reply = await getAIResponse(sessionId, cleanText); // 调用 AI 接口并获取回答
await room.say(reply, msg.talker()); // 回复消息
}
});
// 监听登录和登出事件
bot.on('login', (user) => log.info('AI Chatbot', `${user} logged in`));
bot.on('logout', (user) => log.info('AI Chatbot', `${user} logged out`));
// 启动机器人
bot.start().catch((err) => log.error('AI Chatbot', err));
总结
通过 Wechaty
提供的扫码功能,我们能够非常轻松地在控制台中实现微信机器人的登录。扫码登录过程简单易懂,通过 qrcode-terminal
生成二维码,并在微信中扫码完成登录。一旦登录成功,机器人就能开始监听消息并通过调用第三方AI大模型智能回复。
感兴趣的各位可以去试试~ 关注我,我是石小石~
注:不建议使用个人主微信号尝试,避免官方误封!