One Conversation Multiple Agents and Routing

The uuid is for logging and the string after conversations//say is what they are using for the sender_id.

@app.route(“/conversations/<cid>/say”, methods=[“GET”])

Ok, but you still have to read out the tracker by a custom action somehow? I thought this would be logged automatically when you load the agent with a tracker store. So thheoretically within the webchannel I could write additionally tracker = self.agent.tracker_store.current_state() to get full state with intents etc? That would be awesome. But this function urrent_states takes no senderID.

I see they use the save function self.agent.tracker_store.save(tracker) but this is not implemented in the TrackerStore Class…

The tracker store class is meant to be subclass and not used as is. So it must be Redis or Mongo or InMemory. Also you can access the tracker inside of custom actions.

But why are they using then self.agent.tracker_store.save(tracker) and there is no specification of the tracker store?

Every agent has a tracker_store. If you do not supply one it will create its own InMemoryTrackerStore. That has a method called save(). And saves the tracker in memory

tracker = agent.tracker_store.get_or_create_tracker(sender_id)
state = tracker.current_state(should_include_events=True)
return jsonify({"tracker": state,
                        "messages": out.messages})

Hey Souvik, I know you are using the RedisTrackerStore, however, I had a quick question about the MongoTrackerStore. When I create an InMemoryTrackerStore with the domain=None, rasa picks up the correct domain and has the correct slots. However, when I create a MongoTrackerStore, it does not seem to pick up the correct or updated domain. For example, the tracker still has slots from a previous domain, and if I update it, it does not change.

In what cases and why would you this optional argument domain actually? Just knowing.

this is what happens when you load an agent

def create_tracker_store(store, domain):
        # type: (Optional[TrackerStore], Domain) -> TrackerStore
        if store is not None:
            store.domain = domain
            return store
        else:
            return InMemoryTrackerStore(domain)

meaning your MongoTrackerStore must load the domain file from the model itself and then it should create or save the tracker upon parse for a sender-id

here’s what i do before loading the agent

domain = TemplateDomain.load(os.path.join(model_directory, "domain.yml"),
									 action_factory)

and each time i have a new model, i restart the server

Something weird is happening for me. If I run all of this is a python terminal, it loads the correct tracker from the mongo tracker store. With everything you said, however, if I run my own server, and run this logic every time the server runs, it loads the wrong domain, but it is the same exact code in the same directory.

Souvikg10, is there anyway you and I could get on a quick 15 minute zoom or webex call to figure this out?

yeah sure but probably tomorrow, i am in europe. write me a mail at souvik_g10@yahoo.com

1 Like

@souvikg10 @adrianhumphrey111

I try to understand the role of the domain here for creating the tracker.:

def create_tracker_store(store, domain):
        # type: (Optional[TrackerStore], Domain) -> TrackerStore
        if store is not None:
            store.domain = domain
            return store
        else:
            return InMemoryTrackerStore(domain)

As I see the domain is just a summary of the domain.yml (from TemplateDomain). But where is the tracker state loaded then? I am looking for the point where exactly the old tracker is loaded to continue a conversation. But this point seems that it creates just an empty tracker?

Even more, since this domain is optional for loading the agent, why should I use this? Maybe I miss something here.

@adrianhumphrey111 Have you solved issue? What do you say about my previous post?

@adrianhumphrey111 @souvikg10 I am currently in the same situation, trying to create multiple agents that can interact in one conversation with the user. So I have two models, each trained on a separate dataset, but now how do I make sure that each incoming message is passed to the right agent before it’s processed? how do i go about creating such a workflow? the general assumption is that each agent is trained on a separate stories.md file, where only one of the two agents must be chosen when the bot is loaded. This creates the problem of having to access the other agent agent through the one thats been loaded with the bot, by that i mean you will have to access agent 2 from the action class of agent 1. This doesn;t look like an ideal implementation to me. The way i’m thinking about implementing this is by introducing a third agent that’s only job is to read an incoming message and depending on the classification it redirects the message to one of the two agents. So this third agent will act as a domain classifier for the chatbot. Do you guys think this is feasible? or is there a better way?

What is the functional logic of splitting it in two agents? Language or organisational?

Think about the complexity here

A. your NLU model is probabilistic

B. First Core model is probabilistically determining where to go

C. Either of the domain driven model needs to predict the same way what to do next

You will end up with a less accurate chatbot

First functionally see the reasoning behind splitting the models

Here in my case - it was the language

thank you for the reply. My logic will be organizational, so for a multi agent approach what do you suggest I should do? In my case, I want both models to take part in the same conversation and would like them to share information. for example

  • user input: hello
  • agent_1: hello, how can i help?
  • user input: i would like to place an order
  • agent_1 asks for specifics
  • user replies back with the order details
  • user asks a question that only agent_2 can reply to
  • now agent_2: replies
  • agent 2 engages in a conversation with the user before switching back to agent_1 (say 4-5 turns)
  • agent 1: uses information acquired by agent 2 to tailor a reply

Now the user should not be aware that there’s more than one agent handling the conversation so the transition between agents should be smooth. This example may not justify the use of 2 bots but it should deliver the idea of what im trying to achieve

You can take my example above where i share context between two agents using a redis tracker though the routing in my case simply based on a parameter.

You have to put first topic classification ( in financial case - Daily banking/Transfer/Credits) This MUST be a very simple classifier for you to route to the right agent

Afterwards - you go to your chatbot and use the more specific problem defined classifier and dialogue manager to return the action.

Make sure your first classifier is really good.

Thanks, i’ll try to work it out. Can I email you if i stumble across any issues?

Yes sure - souvik_g10@yahoo.com

1 Like