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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions