microsoft / promptflow

Build high-quality LLM apps - from prototyping, testing to production deployment and monitoring.
https://microsoft.github.io/promptflow/
MIT License
9.31k stars 842 forks source link

Better Conditional Logic for Flows #2088

Open iceman3000 opened 7 months ago

iceman3000 commented 7 months ago

Is your feature request related to a problem? Please describe. I have found huge limitations when using prompt flow in practice due to the very limited "activate config" capabilities. Even simple switch flows (as shown in the prompt flow example) have to be over engineered passing outputs to multiple nodes. In many cases, I find it would be helpful to be able to do a simple if/else based on the previous node. For example it might output false if not to continue, or an object for the next node if it is to continue. Unfortunately, you can only check in activate config if Bool (or whatever), so I can only pass True or False to the next node, rather than the required output in the True case. If you have any complexity to your flow or logic, you end up with lines going everywhere trying to work around the limited conditional capabilities. Currently every possible path needs to have the inputs from the previous node and then each one has to check individually, and it can only check one value "type".

Describe the solution you'd like Allow more flexible conditional logic (including and/or) in the activate config section rather than hard coded states like bool or int etc. Even just a python if statement would be an improvement. As an example, the way Intercom (chat software) allows you to filter through users is a great example of simple UI but powerful conditional logic. Possibly would also be good to have "routing" nodes, where its entire job is to check the input value, and then route the flow accordingly to any number of other paths.

Describe alternatives you've considered Creating highly complex and difficult to follow flows due to all the hidden activate config states and various outputs being passed around. Or doing all logic inside a python node, but this defeats the purpose of having a nice drag and drop UI/flow, I may as well just host a python file and not use prompt flow. Maybe create some custom tool that routes, but I think this is still limited by the capabilities of the activate config

Additional context IMO this is the biggest limiting factor of Promptflow, conditional logic is so important even in the simplest of flows I'm struggling to see value in using Promptflow because of this limitation.

brynn-code commented 7 months ago

Hi @iceman3000 , thanks for reaching us, the statement you described about the condition in flow is true, currently we don't support complex expression in the condition part, it requires more detail design about the expression, we will mark the issue as 'long-term' and update here once we decide to expand our conditional capabilities. Thanks.

thy09 commented 7 months ago

Hi, @iceman3000 , thank you for the feedback. We want to understand more details for such requirements. If I understand correctly, are you asking something like

activate:
    when: ${node.output} is not None
activate:
    when: ${node.output} != False

Or do you have any other typical scenarios?

iceman3000 commented 7 months ago

I think the TLDR is that we need way more flexibility on the conditions in order to even build simple flows, little own complex flows. Quite often, you'll want the flow to run differently or go down a different path depending on the output from the LLM. This is quite difficult to do when the you can only expressly check a single case. The solution currently is build a bunch of nodes, for each of your cases, and then pass the output to all of them, and only the one that matches will execute. Its pointless if you have any more logic to come after this, because you have to then duplicate all your nodes under each case, or you end up with placeholder inputs on following nodes just so you can get the flow to continue past this point.

iceman3000 commented 7 months ago

I think ideally, a path routing on the output of the node would be the most flexible and maintainable solution. Aka, instead of passing the output to all nodes, you can set your conditions on the output. E.g. If output = false, go to node a | elif output.value = abc, go node b | elif output.value = xyz, go to node c

thy09 commented 7 months ago

@iceman3000 Can you explain more details about your proposal? It seems that you want to change the condition check from the input from output, using something like "goto"? Could you provide some examples how will you write such conditions in a DAG based yaml file?

iceman3000 commented 6 months ago

I'm not familiar with YAML sorry.

A recent example where I wanted to use conditions, but could not, was checking the response from the openai call, to see if the tools array was populated (note I had to use a python node to make this call, because tools is not suppoted in the openai tool for promptflow). If the tools array was populated, I needed to then trigger the relevant tools to run in the flow. If it wasn't populated, I needed to trigger the response to user (as all tool calling was now completed).

I can't find a seamless way to do this in promptflow, so I've opted to use a single python node, and do all my tool calling, and open AI functions in there, which kinda defeats the point of promptflow haha.

Note, this routing idea I proposed was more of an alternative feature/approach I suppose, rather than the initial issue, which is that conditional activation is kinda useless in real world applications IMO in its current state.

simoninnyc commented 6 months ago

I agree that the conditional logic needs improving. The activate config feature is fairly limiting and does not enable multiple conditions to be be tested. A common use case might be to execute a node based on whether a variable matches multiple values. I hit this limitation when using a LLM node to classify the user's intent and my intention was to then run one or more nodes depending on the classification. Since the activate config field only takes one value, there was no way to achieve this desired flow. I guess the fallback is to put all the code in a single Python script as the OP suggested.