File size: 2,764 Bytes
57b8424
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from operator import itemgetter
from langchain.runnables.openai_functions import OpenAIFunctionsRouter

from permchain.connection_inmemory import InMemoryPubSubConnection
from permchain.pubsub import PubSub
from permchain.topic import Topic

'''
    This is the research team. 
    It is a group of autonomous agents that work together to answer a given question
    using a comprehensive research process that includes: 
        - Searching for relevant information across multiple sources
        - Extracting relevant information
        - Writing a well structured report
        - Validating the report
        - Revising the report
        - Repeat until the report is satisfactory
'''
class ResearchTeam:
    def __init__(self, research_actor, editor_actor, reviser_actor):
        self.research_actor_instance = research_actor
        self.editor_actor_instance = editor_actor
        self.revise_actor_instance = reviser_actor

    def run(self, query):
        # create topics
        editor_inbox = Topic("editor_inbox")
        reviser_inbox = Topic("reviser_inbox")

        research_chain = (
            # Listed in inputs
            Topic.IN.subscribe()
            | {"draft": lambda x: self.research_actor_instance.run(x["question"])}
            # The draft always goes to the editor inbox
            | editor_inbox.publish()
        )

        editor_chain = (
            # Listen for events in the editor_inbox
            editor_inbox.subscribe()
            | self.editor_actor_instance.runnable
            # Depending on the output, different things should happen
            | OpenAIFunctionsRouter({
                # If revise is chosen, we send a push to the critique_inbox
                "revise": (
                        {
                            "notes": itemgetter("notes"),
                            "draft": editor_inbox.current() | itemgetter("draft"),
                            "question": Topic.IN.current() | itemgetter("question"),
                        }
                        | reviser_inbox.publish()
                ),
                # If accepted, then we return
                "accept": editor_inbox.current() | Topic.OUT.publish(),
            })
        )

        reviser_chain = (
            # Listen for events in the reviser's inbox
            reviser_inbox.subscribe()
            | self.revise_actor_instance.runnable
            # Publish to the editor inbox
            | editor_inbox.publish()
        )

        web_researcher = PubSub(
            research_chain,
            editor_chain,
            reviser_chain,
            connection=InMemoryPubSubConnection(),
        )

        res = web_researcher.invoke({"question": query})
        print(res)
        return res["draft"]