## 🧐 关于 myGPTReader myGPTReader 是一个 Slack 机器人,可以阅读任何网页、电子书、视频(YouTube)或文件,并通过 chatGPT 进行总结。它还可以通过语音与你交谈。 ## 🏁 如何开始 现在加入这个拥有超过 5000 多名成员的[ slack 频道](https://slack-redirect.i365.tech/),免费体验所有这些功能,不仅能使用 chatGPT 的全部功能,还能围观他人的对话,学习如何与 chatGPT 更好的对话。 ![](https://img.bmpi.dev/my-gpt-reader-showcase.gif) ## 🔥 主要功能 ### 📖 快速了解网页内容 使用 myGPTReader 快速阅读,通过对话了解任何网页内容,甚至包括视频(目前仅支持 YouTube 有字幕的视频)。 ![Web read with myGPTReader](https://user-images.githubusercontent.com/2446612/228726895-3c789d54-1b15-4d8e-8022-7bf0b93185ff.gif) ### 📚 阅读文件内容 使用 myGPTReader 快速阅读任何文件的内容,支持电子书、PDF、DOCX、TXT 与 Markdown。 ![Document read with myGPTReader](https://user-images.githubusercontent.com/2446612/228726930-e623c5f2-5cb5-4d93-9ffc-fda5c722a910.gif) ### 🗣️ 直接使用语音对话 myGPTReader 通过用你的声音与 myGPTReader 对话来练习外语,它可以是你的私人外教,支持中文、英语、德语与日语。 ![Voice chat with myGPTReader](https://user-images.githubusercontent.com/2446612/228726952-8dc02828-c540-4cf8-9aff-5b1e81a969d0.gif) ### 💬 与 myGPTReader 对话 内置大量 `prompt` 模板,使用这些模板与 chatGPT 更好的对话。 ![Ask myGPTReader anything](https://user-images.githubusercontent.com/2446612/228726979-15548dc5-2b9a-4fa2-bd52-d2920ab4f81b.gif) ![](https://img.bmpi.dev/my-gpt-reader-prompt-template-1.gif) ### 🔥 今日热点 每天 myGPTReader 会发送最新的热榜新闻并自动生成摘要,方便你快速了解今日热点。 ![Hot News Today](https://user-images.githubusercontent.com/2446612/228729812-38c3137a-026e-4100-9fab-0b8f2a1215fc.gif) ### 如何安装 - 可参考 [@nigdaemon](./docs/how-to-install/nigdaemon.md) 的安装记录。 - 可参考[MyGPTReader 部署到 Fly.io 教程完整记录(全部功能) - GPT4AllPro](https://gpt4all.pro/chatgpt-in-slack-mygptreader-deployment-to-fly-io-tutorial-complete-documentation-all-features/) - 如果想使用 Docker 部署也可参考 [@polly3d](./docs/how-to-install/docker.md) 的安装记录。 ## 源码分析 **依赖:** 基于 openai,llama-index,flask,pyPDF2,docx2txt,youtube-transcript等依赖开发。 llama-index介绍过,将问题字符串转为向量节省token,这样可以发送大量内容,比如pdf文献总结实现 flask搭建简单的api服务 docx2txt,pdf,youtube等实现从word,pdf,youtube等多源加载字问题。 **slack应用** 创建一个slack应用,https://api.slack.com/apps ,创建一个bot,生成 token,那接下来就可以在web api项目中接收slack消息,并回复。。 **bot flask项目** python flask项目,无数据库,可以dockerfile部署。 ``` ["gunicorn", "app.server:app"] ``` ### 每日新闻推送分析: flask 定时任务,每日 1:30 触发: ``` @scheduler.task('cron', id='daily_news_task', hour=1, minute=30) def schedule_news(): logging.info("=====> Start to send daily news!") all_news_blocks = build_all_news_block() send_daily_news(slack_app.client, all_news_blocks) ``` 从以下信息源api获取数据,并调用 openai 进行分析每条链接: ``` zhihu_news = executor.submit(build_zhihu_hot_news_blocks) v2ex_news = executor.submit(build_v2ex_hot_news_blocks) onepoint3acres_news = executor.submit(build_1point3acres_hot_news_blocks) reddit_news = executor.submit(build_reddit_news_hot_news_blocks) hackernews_news = executor.submit(build_hackernews_news_hot_news_blocks) producthunt_news = executor.submit(build_producthunt_news_hot_news_blocks) xueqiu_news = executor.submit(build_xueqiu_news_hot_news_blocks) jisilu_news = executor.submit(build_jisilu_news_hot_news_blocks) ``` 通过多线程返回各数据源热门新闻后,保存为 zhihu_news, v2ex_news 等 list 数据: ``` rss = rss_urls[news_key]['rss']['hot'] hot_news = get_post_urls_with_title(rss['url']) hot_news_blocks = build_slack_blocks( rss['name'], hot_news) ``` 这里 get_post_urls_with_title 传入url,对每个url进行分析: ``` updated_post['summary'] = get_description(entry) ... gpt_answer = get_summary_from_gpt(entry.link) ``` 调用 get_description,即 get_summary_from_gpt 通过openai获取总结: ``` news_summary_prompt = '请用中文简短概括这篇文章的内容。' gpt_response, total_llm_model_tokens, total_embedding_model_tokens = get_answer_from_llama_web([news_summary_prompt], [url]) ``` 调用查询,返回结果: ``` answer = index.query(dialog_messages, llm_predictor=llm_predictor, text_qa_template=prompt) ``` 最后调用slask发送推送: ``` for news_item in news: try: r = client.chat_postMessage( channel=schedule_channel, text="🔥🔥🔥 Daily Hot News 🔥🔥🔥", blocks=news_item, reply_broadcast=True, unfurl_links=False, ) ``` 可以发现,每个数据源都发送一条消息。 ### 阅读文档 比如发送一个url链接,先获取url内容,转换为 llama-index 向量,发送到openai。 比如用户发送一个pdf,并@bot后触发机器人发送消息到api服务器,先调用pyPDF2解析pdf为字符串,index 向量化,发送到openai。 用户发送消息,会调用 ``` @slack_app.event(event="message", middleware=[bot_messages]) def log_message(logger, event, say): try: if is_premium_user(event["user"]): bot_process(event, say, logger) ``` 这里使用的是slack sdk设置一个监听器,接受 slack消息交由 bot_messages 函数处理: ``` def bot_process(event, say, logger): if event.get('files'): ``` 如果发送的是文件,检测文件后缀为pdf,文件大小,然后再下载文件: ``` response = requests.get(url_private, headers={"Authorization": "Bearer " + slack_app.client.token}) ``` ### 语音对话 如果发送的是语音(filetype_voice_extension_allowed = ['m4a', 'webm', 'mp3', 'wav']),检测文件后缀为pdf,文件大小,然后再下载文件: ``` voicemessage = get_text_from_whisper(file_md5_name) ``` flask 添加 handler 消息处理: ``` @app.route("/slack/events", methods=["POST"]) def slack_events(): return slack_handler.handle(request) ``` ## 总结 可以发现: 1、用户上传一个pdf文件,首先会上传到slack服务器,然后再发送到api服务器,api服务器解析为字符串后,最后发送到openai。所以api服务器的上传带宽需要设置较大,否则并行会卡住。 2、无需数据库,提取词由llama—index保存为json数据。 3、处理时间较久,用户交互中直接回复消息,后续通过slack 再主动发送消息。这个和微信公众号类似,不过公众号太奇葩,只支持客服消息接口主动发送消息。