diff --git a/.gitignore b/.gitignore index 30803ea77..02baa679c 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,5 @@ plugins/banwords/lib/__pycache__ !plugins/keyword !plugins/linkai !plugins/jina_sum +!plugins/jina_sum/**/ client_config.json diff --git a/README.md b/README.md index 827d06538..1e9b8917f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,13 @@ - [ ] **飞书** 待测试 # 最新功能 -## 1. Suno音乐插件 +## 1. 集成[JinaSum](https://github.com/hanfangyuan4396/jina_sum)插件 +使用Jina Reader和ChatGPT支持总结公众号、小红书、知乎等分享卡片链接,配置详情请查看[JinaSum](https://github.com/hanfangyuan4396/jina_sum) + +![plugin-jinasum-1](./plugins/jina_sum/docs/images/wechat_mp.jpg) +![plugin-jinasum-1](./plugins/jina_sum/docs/images/red.jpg) + +## 2. Suno音乐插件 使用 [Suno](https://github.com/hanfangyuan4396/suno) 插件生成音乐 ![plugin-suno-1](./docs/images/plugin-suno-1.jpg) @@ -40,11 +46,11 @@ https://github.com/hanfangyuan4396/dify-on-wechat/assets/43166868/396fa76f-a5d9-4de2-8ce2-365ceb6684f0 -## 2. 支持Dify Chatflow & Workflow +## 3. 支持Dify Chatflow & Workflow dify官网已正式上线工作流模式,可以导入本项目下的[dsl文件](./dsl/chat-workflow.yml)快速创建工作流进行测试。工作流输入变量名称十分灵活,对于**工作流类型**的应用,本项目**约定工作流的输入变量命名为`query`**,**输出变量命名为`text`**。 (ps: 感觉工作流类型应用不太适合作为聊天机器人,现在它还没有会话的概念,需要自己管理上下文。但是它可以调用各种工具,通过http请求和外界交互,适合执行业务逻辑复杂的任务;它可以导入导出工作流dsl文件,方便分享移植。也许以后dsl文件+配置文件就可以作为本项目的一个插件。) -## 3. 支持COZE API +## 4. 支持COZE API ![image-5](./docs/images/image5.jpg) @@ -52,7 +58,7 @@ dify官网已正式上线工作流模式,可以导入本项目下的[dsl文件 -### 3.1 如何快速启动coze微信机器人 +### 4.1 如何快速启动coze微信机器人 - 请参照**快速开始**步骤克隆源码并安装依赖 @@ -88,6 +94,7 @@ python3 app.py # windows环境下该命令通 # 更新日志 +- 2024/04/24 集成JinaSum插件,修复总结微信公众号文章,修复dify usage key error, 修复dify私有部署的图片url错误 - 2024/04/16 支持基本的企业微信客服通道,感谢[**@lei195827**](https://github.com/lei195827), [**@sisuad**](https://github.com/sisuad) 的贡献 - 2024/04/14 Suno音乐插件,Dify on WeChat对接详细教程,config文件bug修复 - 2024/04/08 支持聊天助手类型应用内置的Chatflow,支持dify基础的对话Workflow diff --git a/bot/dify/dify_bot.py b/bot/dify/dify_bot.py index 3bf005589..44d814b49 100644 --- a/bot/dify/dify_bot.py +++ b/bot/dify/dify_bot.py @@ -29,7 +29,7 @@ def reply(self, query, context: Context=None): user = None if channel_type == "wx": user = context["msg"].other_user_nickname if context.get("msg") else "default" - elif channel_type in ["wechatcom_app", "wechatmp", "wechatmp_service"]: + elif channel_type in ["wechatcom_app", "wechatmp", "wechatmp_service", "wechatcom_service"]: user = context["msg"].other_user_id if context.get("msg") else "default" else: return Reply(ReplyType.ERROR, f"unsupported channel type: {channel_type}, now dify only support wx, wechatcom_app, wechatmp, wechatmp_service channel") @@ -46,7 +46,7 @@ def reply(self, query, context: Context=None): reply = Reply(ReplyType.ERROR, "Bot不支持处理{}类型的消息".format(context.type)) return reply - def _get_api_base_url(self): + def _get_api_base_url(self) -> str: return conf().get("dify_api_base", "https://api.dify.ai/v1") def _get_headers(self): @@ -109,7 +109,9 @@ def _handle_chatbot(self, query: str, session: DifySession): # "created_at": 1705407629 # } rsp_data = response.json() - logger.debug("[DIFY] usage ".format(rsp_data['metadata']['usage'])) + logger.debug("[DIFY] usage {}".format(rsp_data.get('metadata', {}).get('usage', 0))) + # TODO: 处理返回的图片文件 + # {"answer": "![image](/files/tools/dbf9cd7c-2110-4383-9ba8-50d9fd1a4815.png?timestamp=1713970391&nonce=0d5badf2e39466042113a4ba9fd9bf83&sign=OVmdCxCEuEYwc9add3YNFFdUpn4VdFKgl84Cg54iLnU=)"} reply = Reply(ReplyType.TEXT, rsp_data['answer']) # 设置dify conversation_id, 依靠dify管理上下文 if session.get_conversation_id() == '': @@ -145,7 +147,8 @@ def _handle_agent(self, query: str, session: DifySession, context: Context): reply = Reply(ReplyType.TEXT, msg['content']) channel.send(reply, context) elif msg['type'] == 'message_file': - reply = Reply(ReplyType.IMAGE_URL, msg['content']['url']) + url = self._fill_file_base_url(msg['content']['url']) + reply = Reply(ReplyType.IMAGE_URL, url) thread = threading.Thread(target=channel.send, args=(reply, context)) thread.start() final_msg = msgs[-1] @@ -153,7 +156,8 @@ def _handle_agent(self, query: str, session: DifySession, context: Context): if final_msg['type'] == 'agent_message': reply = Reply(ReplyType.TEXT, final_msg['content']) elif final_msg['type'] == 'message_file': - reply = Reply(ReplyType.IMAGE_URL, final_msg['content']['url']) + url = self._fill_file_base_url(final_msg['content']['url']) + reply = Reply(ReplyType.IMAGE_URL, url) # 设置dify conversation_id, 依靠dify管理上下文 if session.get_conversation_id() == '': session.set_conversation_id(conversation_id) @@ -191,6 +195,15 @@ def _handle_workflow(self, query: str, session: DifySession): reply = Reply(ReplyType.TEXT, rsp_data['data']['outputs']['text']) return reply, None + def _fill_file_base_url(self, url: str): + if url.startswith("https://") or url.startswith("http://"): + return url + # 补全文件base url, 默认使用去掉"/v1"的dify api base url + return self._get_file_base_url() + url + + def _get_file_base_url(self) -> str: + return self._get_api_base_url().replace("/v1", "") + def _get_workflow_payload(self, query, session: DifySession): return { 'inputs': { diff --git a/plugins/jina_sum/.gitignore b/plugins/jina_sum/.gitignore deleted file mode 100644 index 7a3d4b1ca..000000000 --- a/plugins/jina_sum/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -__pycache__/ -config.json diff --git a/plugins/jina_sum/docs/images/csdn.jpg b/plugins/jina_sum/docs/images/csdn.jpg new file mode 100644 index 000000000..ab98e3b71 Binary files /dev/null and b/plugins/jina_sum/docs/images/csdn.jpg differ diff --git a/plugins/jina_sum/docs/images/red.jpg b/plugins/jina_sum/docs/images/red.jpg new file mode 100644 index 000000000..e8fb74066 Binary files /dev/null and b/plugins/jina_sum/docs/images/red.jpg differ diff --git a/plugins/jina_sum/docs/images/wechat_mp.jpg b/plugins/jina_sum/docs/images/wechat_mp.jpg new file mode 100644 index 000000000..42a1359a3 Binary files /dev/null and b/plugins/jina_sum/docs/images/wechat_mp.jpg differ