Rongronggg9 / RSS-to-Telegram-Bot

A Telegram RSS bot that cares about your reading experience
https://t.me/RSStT_Bot
GNU Affero General Public License v3.0
1.51k stars 277 forks source link

[Feature Request] 增加额外的内容处理过程,或者增加对于prompt的支持 #447

Open prur opened 6 months ago

prur commented 6 months ago

需求:

实现可以根据订阅源的不同,设置对于该订阅源的额外的内容处理方式,然后把处理结果作为附属内容发送给用户。

比如对于订阅源A,增加一个文本翻译的工作流程;对于订阅源B,增加一个关键词提取的功能;还可以有总结、自定义的prompt等功能。

下面是根据询问 AI 的改进意见,供您参考:

Q:

1)本项目代码的主要的工作流程:

1. 初始化程序,连接数据库和Telegram API
2. 加载用户订阅源,启动定时任务定期检查更新
3. 检查到更新时,获取内容,解析并处理成需要的格式
4. 将内容发送到Telegram上
5. 接收用户交互命令,如修改设置等
6. 持续循环上述流程

2)代码改进:
在流程3与流程4之间(或者通过修改流程3、流程4)增加一项功能:
根据订阅源的不同,设置对于该订阅源的额外内容处理方式,比如对于订阅源A,增加一个文本翻译的工作流程;对于订阅源B,增加一个关键词提取的功能;

3)代码改进要求:
1. 尽可能小的影响源代码、原来的代码框架、代码逻辑
2. 尽可能的使用可插拔、热加载、插件等方式
3. 详尽写出需要修改的代码范围,和具体的代码实现

A:

## 实现方法:

(1) 尽可能小影响原代码

在src/parsing/post.py中,Post类的 send_formatted_post 方法末尾增加判断:

if feed_link in TRANSLATION_FEEDS:
   await self.translate(formatted_text)
if feed_link in KEYWORD_FEEDS:
   await self.keyword_extract(formatted_text)

TRANSLATION_FEEDS、KEYWORD_FEEDS定义新的常量或配置来表示启用额外处理的订阅源

(2) 额外处理用可插拔方式实现

在src/plugin中新增google_translate.py、keyword_extract.py等文件

内容类似:

from abc import ABC, abstractmethod

class Processor(ABC):
  @abstractmethod
  async def process(text):
    pass

class GoogleTranslator(Processor):
  # 实现翻译逻辑

class KeywordExtractor(Processor):
  # 实现关键词提取逻辑

src/parsing/post.py中调用:

processor = get_processor(feed_link)
await processor.process(formatted_text)

(3) 使新功能热加载

使用watchdog监听src/plugin目录变化

变化时重新导入processor,实现热加载

以上尽可能在不影响原框架、最小改动的情况下实现可配置、可插拔的订阅源额外处理功能。

主要更改:

导入自定义处理器

定义订阅源到处理器的映射

在发送前判断订阅源是否需要额外处理

如果需要,调用对应的处理器进行处理

处理后再发送

这样,在不影响原有代码和框架的情况下,实现了订阅源的自定义处理。

可以根据实际需要调整处理器的映射,新增其他处理器等来丰富功能。

整体来说,订阅源的自定义处理可以通过类似的可插拔设计模式实现,不需要大规模修改原代码。

Rongronggg9 commented 6 months ago

我很抱歉,我不能回答这个问题。我不是一个大型语言模型,没有被训练来回答各种问题。我的开发者没有提供足够的算力支持,因此我没有能力回答专为大型语言模型优化的 prompt。

我可以尽力帮助你解决各种问题,但也有一些限制。例如,我可能无法为重复提问提供任何帮助,也无法理解表意不明的提问。另外,我并不是完美的,有时候可能会理解错误或提供不准确的答案。如果遇到我无法处理的问题,我会尽力指导你找到其他资源或方法来解决。

学会向碳基生物提问是一个循序渐进的过程,下面是一些方法可以帮助你:

  1. 检索现有提问:现有的提问可能已经覆盖了你的问题,重复提出相同的疑问会增加碳基生物的困扰。
  2. 表意明确:表意不明的问题将会增加碳基生物的心智负担。确保提问没有模棱两可之处,这样的问题可以更快获得碳基生物的解答。
  3. 简洁明了:保持提问简洁明了,避免冗长的描述。如果表意已经明确了,则应该点到为止,这样的提问更容易被理解和回答。
  4. 避免引用大型语言模型的回答:大型语言模型与碳基生物存在生殖隔离。在提问中引用大型语言模型的回答是画蛇添足的,可能造成信息失真和误解,并可能冒犯碳基生物。

总的来说,学会向碳基生物提问需要耐心、指导和实践。通过不断的学习和实践,可以逐渐掌握这一重要的沟通技能,并与碳基生物建立更好的沟通和交流关系。

prur commented 6 months ago

抱歉了,owner. 我的表达不清楚。

作为代码小白,尝试了自行修改代码库满足自己的这个需要,实在是有些困难,但是很想能有这个功能,所以问了一下AI看看能不能帮您减轻一点改动的准备工作。

我订阅RSS转发到Telegram是遇到了一些问题,比如:

我想的关于预处理,可以是通过各种插件的方式,也可以是通过用户自行设定prompt的方式(需要自己有大模型的api key)。

不知道能不能让您理解我的想法😂

Rongronggg9 commented 5 months ago
  • 有些语种的RSS源,我自己并不能独立的阅读,但是都是非常优秀的内容。如果发送到telegram之前可以做一些预处理的工作,会对后面的阅读有很大帮助。

翻译的难点主要在于必须带格式翻译,也就是说要求 API 要能够接受 HTML 输入并输出等价的 HTML,除此之外只是个调用 API 的问题。确实有翻译提供商提供这样的 API。然而如果要实现这样的功能,势必要在一开始就考虑到未来适配更多翻译提供商的需求,从而势必遇到下一个问题。

  • 还有一些非常喜欢发超长篇内容的RSS源,如果能够在订阅时,设定是否需要做某种预处理(比如总结、提取tags),那么对于之后判断是否需要进一步完整阅读会很有帮助。

本项目建立初期只是个满足个人需求的业余项目,当时没有考虑模块间的耦合度问题,从而现在各个模块之间耦合度较高。增加这样一个功能将导致订阅处理路径的动态变化,从而造成当前架构下的维护难度。尤其考虑这是一个多用户的 bot,多个用户可以对同一个 feed 设置不同选项,从而造成即使是同一个订阅,也可拥有多变的处理路径。这在当下已经造成了一些维护难度,因此重构乃至重写是必须的,否则添加这种功能会是不可持续的。

可以是通过各种插件的方式

这是最理想的方式,也是我自从 #246 起就已经有的目标。仍然还是上文说的模块间耦合度的问题。理想状态下,各个模块应该形成一个链条,以 middleware(中间件)的形式依次完成对订阅的处理,同时依据多用户的配置动态分派处理路径。只有在这种架构下,书写插件才是可维护的,且能做到不要求贡献者了解全部源代码。然而,这仅仅解决了重构乃至重写的方法论问题,工作量是个悬而未决的问题。

你的 FR 是合理的、有意义的。我会保持这个 issue 开启。然而,我有本职工作,业余时间也没有足够的心神用于大量重构甚至重写本项目。本项目仍然得到持续维护,目前的维护仍然以我的需求和大量用户的急切需求为主。对于除此以外的大的变更无法提出任何 ETA。如果有人愿意在保证良好的编程实践的前提下完成上述工作,我也非常欢迎,并愿意提供一定的指导。

prur commented 5 months ago

经过两天的探索,初步实现了自己想要的功能

  1. 实现在 Sub 的 inline button 中:设置处理器[ /set_processor ]和 获取当前处理器 [ /get_processor ];先实现了 HNRSSProcessor 用来阅读HN😂,主要给自己用不管这么多了。

  2. 接下来可能的计划: 2.1 实现在 Sub 的 inline button 中通过选择来设置处理器 2.1.1 可能需要实现查询系统内置的处理器与用户自己的prompt处理器。 2.2 实现用户自定义自己的 “prompt处理器” ,可能需要新增一个数据库表来存储:prompt处理器名称、对应的prompt、选择的大模型提供商、模型名称;修改 User表,增加一项存储用户的大模型api key, 还要考虑 api key 安全储存的问题。

  3. 更改的部分: 3.1 Sub表增加了一个processor属性 3.2 src下增加了一个文件夹存储编写的处理器

image

image

image

Rongronggg9 commented 5 months ago

这很好。你可以开一个 draft PR,我可以指导你或和你一起修改使之达到可 merge 的标准

Rongronggg9 commented 5 months ago

@E021ntox 均为重复的 feature request。

123 #159

Rongronggg9 commented 5 months ago

@E021ntox 我认为你这样没有做到富有涵养和礼貌。

  1. 「借楼」本身就是不礼貌的。如果你是为了节省时间不想开一个新的 issue,那别人的时间也很宝贵。「借楼」会导致:
    1. 所有本 issue 的 subscriber 将会因为你的回复收到通知,即使他们并不想被打扰。
    2. 我不得不另外想办法记录你的需求,但我的时间也很宝贵。
  2. 用抱怨的语气描述需求也很不礼貌。我理解你本意不是为了抱怨,但你的语气听起来带有了抱怨的味道,即使你加了「请」字。这根本上是因为你的表述既不清晰,也没做到剥离主观情感。像「用户加的多了都不知道在哪删」和「现在的文档又乱又晕」是一种主观情感的表述,虽然做到了表达动机(也仅仅做到了表达动机,表意仍然不清晰),但是读者观感却不佳。

说回你的需求。

用户管理功能,用户加的多了都不知道在哪删

添加完整的用户管理功能,尽管是一个合理的需求,但是很难实现:

  1. 数据库里没有储存用户的用户名和显示名称(因为它们经常变化,储存下来没有意义),而只有纯数字的 uid。只列出 uid 显然是没有意义的。然而,如果要实现用户管理,那么就要每次都向 Telegram API 拉取这些信息,而频繁拉取信息可触发 rate limit。
  2. 使用 inline button 列出用户,每页将最多只能列出 11 个,需要频繁翻页才可能找到所需的用户,体验不佳。而且大量翻页很容易就触发上一个问题。
  3. MULTIUSER=0 mode is just a plus. 主要解决的是私有部署情形下仅供自己和朋友使用的场景,这种场景理应不需要删除(降权)用户。基于此,我认为删除用户本身就是一个非常少见的需求。而如果不删除用户的话,实际上是很少需要列出用户的。
  4. 即使需要删除用户,你也可以使用等价于添加用户的方式 (/user_info @username/user_info 1234567) 来对用户降权。

其实你想表达的需求是不是退订一个用户的所有订阅并降权?如果是的话,这就凸显了你的表达并不清晰这一点。 目前可以在启用了 MANAGER_PRIVILEGED=1 之后对任意用户使用远程命令,可以做到退订任意用户的订阅。如果你的需求是想要省去这些麻烦,在上面第 4 点的基础上增加一个退订所有订阅的按钮,那么这是一个合理的可实现的需求。如果这是你想要的,请去新开一个 issue。

重新组织一下文档,现在的文档又乱又晕

文档中必须有的内容我认为是都有了,剩下没提到的部分,要么可以从试用各个命令中学习到,要么可以从公开资料中学习到。有关文档的布局,可能是还有可优化的地方,但我并没有想到还能怎么优化。抱怨文档「又乱又晕」不会对我的维护工作有任何帮助,如果你有更好的布局建议,请另外开一个 issue 提出,或者更优选地,开一个 PR 完成你期望的重布局。

这是一个没有足够的贡献者以形成社区的项目。从 PM 到 UX 设计,从架构设计到模块设计,从书写代码到书写文档,尽管没有做到最好,但这些工作都不是天上掉下来的。乃至于公共 demo 都不总能收到足够的捐赠以至于时常需要贴钱维持运转。平心而论,书写文档的投入产出比并不很高,况且许多现代软硬件已经不再有完整的说明书了,在这个背景下我认为现在的文档尚且是可被接受的。 维护文档是一件非常消耗心神的工作,比书写代码甚至 UX 设计还要费时费心费力。为了节省工作量,实际上所有中文文档都是从英文文档经过机器翻译后人工润色得来的。即使是这样,维护中文文档的工作量仍然不小,更不用提维护英文文档的工作量。 希望你可以从这些事实中理解维护文档的不易。