Skip to content

PocketFlow编排能力进一步增强的思考 #110

@mossexplore

Description

@mossexplore

PocketFlow的设计理念非常出色。在当前Agent应用场景中,大部分都是基于工作流模式的,因此采用Flow的方式确实能带来显著效果。经过深入使用后,我认为可以进一步优化其组件设计,将其原子化程度提升到更高水平。理想状态下,开发者只需编写简单的流程编排代码即可完成复杂任务,例如:QuestionNode >> LLMNode >> RAGNode。更进一步说,如果原子化能力足够强大,甚至可以将Dify这样的低代码编排流程转换为PocketFlow的高代码实现。我已经验证过这个方向的可行性,目前遇到的主要挑战在于数据共享机制。当前PocketFlow通过shared对象在Node间共享数据,每个Node可以自由定义输出到shared的数据。然而在实际应用中,由于每个Node的输入需求各不相同,导致在流程编排时经常需要重新调整每个Node的输入输出配置,这给使用带来了诸多不便。

举一个简单的例子:

class QuestionNode(Node):
    def prep(self, shared):
        return shared

    def exec(self, prep_res):
        question = prep_res["question"]
        return question

    def post(self, shared, prep_res, exec_res):
        shared["question"] = exec_res
		

class LLMNode(Node):

    def prep(self, shared):
        llm_messages = shared["llm_messages"]
        return llm_messages

    def exec(self, llm_messages):
        response = call_llm(llm_messages)
        return response.choices[0].message.content

    def exec_fallback(self, prep_res, exc):
        return "There was an error processing your request in LLMNode."

    def post(self, shared, prep_res, exec_res):
        shared["llm_response"] = exec_res

在编排QuestionNode >> LLMNode时,发现节点间的输入输出不兼容。目前考虑两种解决方案:
(1)修改QuestionNode的输出格式以适配LLMNode的输入。虽然这能解决当前问题,但存在明显的局限性。当需要将QuestionNode与其他类型的节点(如XXNode)连接时,可能又需要再次修改QuestionNode的输出格式,这会导致:

  • 代码维护困难,需要不断调整QuestionNode的实现
  • 可能破坏现有QuestionNode与LLMNode的连接逻辑
  • 违反开闭原则,对扩展开放但对修改关闭

(2)通过继承机制,创建QuestionNode或LLMNode的子类并重写prep/post方法。这种方法虽然更符合设计原则,但也存在以下问题:

  • 代码冗余增加,需要为每种连接组合创建专门的适配类
  • 系统复杂度提升,增加了类的数量
  • 使用体验下降,需要开发者了解并选择正确的适配类

因此,希望对共享数据shared可以进一步改进。或者这样有没有更好的实现方式,希望给一些指导,谢谢。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions