Skip to content

Commit 061ad7d

Browse files
authored
利用 Dify 构建基于 GPT-4 Turbo 的智能 Agent,实现医疗微信机器人 (#183)
* 利用 Dify 构建基于 GPT-4 Turbo 的智能 Agent,实现医疗微信机器人 * 利用 Dify 构建基于 GPT-4 Turbo 的智能 Agent,实现医疗微信机器人 * 利用 Dify 构建基于 GPT-4 Turbo 的智能 Agent,实现医疗微信机器人 * 利用 Dify 构建基于 GPT-4 Turbo 的智能 Agent,实现医疗微信机器人 * 利用 Dify 构建基于 GPT-4 Turbo 的智能 Agent,实现医疗微信机器人 * 0.11.66 * 利用 Dify 构建基于 GPT-4 Turbo 的智能 Agent,实现医疗微信机器人_refined * 0.11.67 * 利用 Dify 构建基于 GPT-4 Turbo 的智能 Agent,实现医疗微信机器人_refined * 0.11.68 * 利用 Dify 构建基于 GPT-4 Turbo 的智能 Agent,实现医疗微信机器人_refined * 0.11.69 * 修改文件夹名称,先删除 * 0.11.70 * 修改文件夹名称,再重建 * 0.11.71 * 代码按照reviewer修改 * 0.11.72
1 parent 1446876 commit 061ad7d

File tree

5 files changed

+188
-1
lines changed

5 files changed

+188
-1
lines changed

jekyll/_contributors/gscfwid.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
name: gscfwid
3+
site: "https://github.com/gscfwid"
4+
bio: An anesthetist in a big ship of mainland.
5+
avatar: /assets/contributors/gscfwid/avatar.webp
6+
7+
---
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
---
2+
title: "利用 Dify 构建基于 GPT-4 Turbo 的智能 Agent,实现医疗微信机器人"
3+
author: gscfwid
4+
categories: article
5+
tags:
6+
- dify
7+
- gpt4-turbo
8+
image: /assets/2024/03-wechatbot-with-wechaty-dify-gpt4/bp-post.webp
9+
---
10+
11+
> 作者: [gscfwid](https://github.com/gscfwid/),An anesthetist in a big ship of mainland.
12+
13+
大家好,我是一名医生,同时也是一个技术爱好者。今天我想和大家分享一下我最近的一个项目——利用 Dify 构建基于 GPT-4 Turbo 的智能 Agent,实现高级微信聊天机器人。
14+
15+
## 为什么选择微信机器人
16+
17+
首先,我想说一下为什么要做这个机器人。作为一名医生,我的一项重要工作是随访病人,了解他们术后的恢复情况。我们医院每年有 7-8 万的手术量,人工电话随访是非常不现实的。而且,现在运营商对电话的限制也比较严格。我发现,对于病人来说,微信可能是一个更容易接受的随访方式,因为它不会显得打扰到他们的生活。
18+
19+
## 为什么选择 Wechaty
20+
21+
然而,市面上大多数微信机器人框架都是基于 web 协议的,而目前 web 协议基本处于不可用的状态。例如,虽然 wechaty 可以利用 UOS 上保留的 web 协议,但它无法获取永久的 ID、备注、tag 等数据,这对随访工作非常不利。在尝试了 padlocal 协议后,我觉得它非常适合我的需求。
22+
23+
## 为什么选择 Dify
24+
25+
接下来,我想说一下为什么选择使用 Dify 来构建这个机器人。首先,我希望这个机器人不仅能完成随访任务,还能成为一个面向病人的医学科普机器人。随着大语言模型的爆发,这个想法变得非常容易实现。利用 wechaty 和大模型的 API,我很快就构思出了一个初步的框架。
26+
27+
Dify 是一个知名的大模型 Agent 平台,它对 API 的封装要比 OpenAI 官方的 API 更加友好,例如在 prompt 的构建和对话线程的保持方面。虽然 OpenAI 也可以构建 assistant,但是保持对话似乎没有那么容易。另外,Dify 平台本身也构建了一些插件,比如 Google 搜索,可以很容易集成到 API 中。因此,我最终选择了 Dify 作为我的开发平台。
28+
以上就是我开发这个微信医疗随访机器人的一些背景和思路。作为一个医生和技术小白,我希望通过分享自己的项目经历,能给大家带来一些启发和思考。在接下来的部分,我会和大家聊聊这个机器人的一些技术细节,欢迎大家提出宝贵的意见和建议。
29+
30+
## 通过 Dify 创建基于 GPT-4 Turbo 的模型
31+
32+
Dify 提供了一个简单易用的界面,让我可以快速地创建和测试模型。
33+
首先,我在 Dify 平台上创建了一个新的应用,并选择了 GPT-4 Turbo 作为基础模型。在这个初始阶段,我暂时没有使用任何自定义的 prompt 或插件,只是想先做一个简单的测试,看看模型的性能如何。
34+
35+
创建应用后,Dify 会自动生成一个 API 密钥(API key),我们可以使用这个密钥来调用 Dify 的 API 接口,与我们创建的智能对话模型进行交互。
36+
37+
## 使用 Wechaty 实现微信机器人
38+
39+
有了智能对话模型,接下来我们需要一个平台来实现微信机器人,将模型集成到微信中。这里我选择了 Wechaty。Wechaty 是一个开源的对话机器人 SDK,支持个人微信号,使用 Node.js 和 TypeScript 构建。
40+
41+
下面是我的代码实现,主要分为以下几个部分:
42+
43+
首先,我使用 wechaty-puppet-padlocal 作为 Wechaty 的 Puppet Provider,它通过 iPad 协议连接微信,相比 Web 协议更加稳定可靠。然后使用 WechatyBuilder 来构建我们的机器人实例。
44+
45+
```javascript
46+
// 初始化Wechaty
47+
const { PuppetPadlocal } = require("wechaty-puppet-padlocal");
48+
const { WechatyBuilder } = require("wechaty");
49+
50+
const puppet = new PuppetPadlocal({
51+
token: process.env.PUPPET_PADLOCAL_TOKEN,
52+
});
53+
54+
const bot = WechatyBuilder.build({ puppet, name: "test" });
55+
```
56+
57+
接下来调用 Dify API 的核心函数。我使用 axios 库发送 POST 请求到 Dify 的 API 端点,传入用户的输入消息、对话 ID 等参数,并通过 API Key 进行身份验证。Dify 会返回智能对话模型生成的回复。
58+
59+
```javascript
60+
// 调用Dify API的函数
61+
const difyApiKey = process.env.DIFY_API_KEY;
62+
const difyApiUrl = "https://api.dify.ai/v1/chat-messages";
63+
64+
async function sendMessage(message, userName) {
65+
// ...
66+
try {
67+
const response = await axios.post(
68+
difyApiUrl,
69+
{
70+
inputs: {},
71+
query: message,
72+
response_mode: "streaming",
73+
conversation_id: conversationData.conversationId,
74+
user: userName,
75+
files: [],
76+
},
77+
{
78+
headers: {
79+
Authorization: `Bearer ${difyApiKey}`,
80+
"Content-Type": "application/json",
81+
},
82+
}
83+
);
84+
// Process response...
85+
} catch (error) {
86+
if (error.response) {
87+
console.error(
88+
"Dify API responded with status code:",
89+
error.response.status
90+
);
91+
} else if (error.request) {
92+
console.error("No response received from Dify API:", error.request);
93+
} else {
94+
console.error("Error setting up request to Dify API:", error.message);
95+
}
96+
// Handle error appropriately...
97+
}
98+
// ...
99+
}
100+
```
101+
102+
最后,我监听 Wechaty 的 message 事件,当收到用户在群聊中@机器人的消息时,提取出消息内容,调用 sendMessage 函数获取智能回复,然后通过 room.say 将回复发送到群聊中。
103+
104+
```javascript
105+
// 监听消息事件
106+
bot.on("message", async (message) => {
107+
// 获取发消息人的信息
108+
const id = message.talker().id;
109+
const room = message.room();
110+
const userName = message.name();
111+
const text = message.text();
112+
// 判断它是否在我已经创建好的SQLite数据库中
113+
if (!room) {
114+
const query = "SELECT * FROM contacts WHERE id = ?";
115+
try {
116+
const row = await db.get(query, [id]);
117+
if (row != undefined) {
118+
const reply = await sendMessage(text, userName);
119+
await message.talker().say(reply);
120+
}
121+
} catch (err) {
122+
console.error(err.message);
123+
}
124+
}
125+
});
126+
```
127+
128+
这里需要强调的一点是,我利用 Dify API 中的 conversation_id 来实现保持对话的功能。这部分代码主要在 sendMessage 函数中:
129+
130+
```javascript
131+
const conversationMap = new Map(); // 创建一个键值对来保存提问者的信息和conversation_id
132+
const CONVERSATION_EXPIRATION = 5 * 60 * 1000; // 设定conversation的保持时间,设定为5分钟
133+
async function sendMessage(message, userName) {
134+
// ...
135+
let conversationData = conversationMap.get(userName);
136+
const timestamp = Date.now();
137+
138+
// 如果会话不存在或已过期,则创建新的会话
139+
if (
140+
!conversationData ||
141+
timestamp - conversationData.timestamp > CONVERSATION_EXPIRATION
142+
) {
143+
conversationData = { conversationId: null, timestamp };
144+
conversationMap.set(userName, conversationData);
145+
}
146+
147+
const response = await axios.post(
148+
difyApiUrl,
149+
{
150+
// ...
151+
conversation_id: conversationData.conversationId,
152+
user: userName,
153+
// ...
154+
}
155+
// ...
156+
);
157+
158+
// 更新会话ID和时间戳
159+
conversationData.timestamp = timestamp;
160+
161+
// ...
162+
// 下面的代码是由于使用了stream模式来获取Dify的response,所以我需要遍历它的每个回复,找到最终的回复内容
163+
for (const line of lines) {
164+
if (line.startsWith("data:")) {
165+
const data = JSON.parse(line.slice(5).trim());
166+
if (data.event === "agent_thought") {
167+
// ...
168+
conversationData.conversationId = data.conversation_id;
169+
}
170+
}
171+
}
172+
// ...
173+
}
174+
```
175+
176+
通过这种方式,我们可以为每个用户维护一个独立的对话上下文,实现多轮对话。当用户在一定时间内(这里设置为 5 分钟)继续发送消息时,就可以保持上下文连贯;如果超过了这个时间,就会开始一个新的对话。
177+
178+
接下来的设置就都是在 Dify 平台了,目前我还在制作中。我设想是上传从网络中下载的科普文章作为知识库,限定 GPT-4 只在知识库中作答。Anyway,就不属于技术讨论的范畴了。
179+
180+
以上就是利用 Dify 和 Wechaty 实现微信智能对话机器人的核心代码。通过 Dify 强大的对话模型和 Wechaty 方便的微信集成,我们可以快速搭建一个实用的医疗科普机器人。当然,这只是一个基础版本,我们还可以继续添加更多功能,如自定义 prompt、知识库搜索等,来进一步提升机器人的智能化水平。
Binary file not shown.
14.2 KB
Binary file not shown.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "wechaty-jekyll",
3-
"version": "0.11.65",
3+
"version": "0.11.72",
44
"description": "Wechaty Official Website for News, Blogs, Contributor Profiles",
55
"private": true,
66
"type": "module",

0 commit comments

Comments
 (0)