Find answers from the community

Updated 2 months ago

Hitl

Hi all, I've been looking at the human-in-the-loop workflow example and trying to figure out how to make this work in a web-based chat interface. That is, instead of using input() to get user input, the input comes from a websocket connection from a frontend web app.

The approach I'm taking at the moment is to have a nested workflow as suggested in the documentation, where the main workflow directs the user input to a sub-workflow depending on the query and existing context state.

Is this a viable approach or is there some other obvious way to yield control back to the user? I'm having some trouble getting the streaming to behave properly (see my question in #❓py-issues-and-help), but want to make sure I'm on the right track before spending too much more time trying to debug it.
L
r
l
12 comments
This approach is ok-ish, working on adding a dedicated human input/response event where, when streaming events, if a human event is emitted, the user can manually provide the human response, using whatever method they want (hoping to get that in tomorrow actually)
That would be great! I tried a very similar approach myself yesterday but couldn't figure out how the workflow execution lifecycle would work in that scenario. How would the user input get passed back into the workflow?
For context, in my code, I had an on_websocket_connect function that kicked off the workflow and streamed events until a HumanInputEvent was encountered, at which time I returned from the function so that the user could post a message.

Then in my on_websocket_message function, I wasn't sure how to pass the message back into the workflow, or how to manage the workflow timing out (besides disabling timeouts altogether).
That's why I moved to a nested workflow approach where the workflow actually completes with a StopEvent each time, so I can yield control back to the UI for subsequent messages.
Imagine this

Plain Text
handler = workflow.run()
async for ev in handler.stream_events():
  if isinstance(ev, InputRequired):
  handler.send_event(HumanResponse(response="...")
Then you can get the human response any way you want -- input, websocket, etc.
And you'll probably have a step waiting for a HumanResponse event
Ah, I see. Sounds good.
You can technically do this today, but human in the loop is so useful, makes sense to have these events just built in
I'm trying this now. Looks like there might need to be some validation rules relaxed for this to work? I get errors saying my InputRequired event is produced but never consumed.
Just disabled validation for the meantime.
Hi, I was look around for similar solution as well, in the end I build something (not sure if it's best practice😋) with Streamlit and FastAPI. Basically in the workflow whenever user input is needed, it's set as an awaitable Future() and the backend streams the event to the frontend. On the frontend part, there is a separate event loop (from the main one Streamlit is running) that gets the backend streamed event and gather user input. Here are the implementation if you are interested:
Workflow code
Backend code
Frontend code
Add a reply
Sign up and join the conversation on Discord