Creating Character Profiles

First, we import modules and create a GPT-4 model instance with the LangChain wrapper, along with an embedding model and text splitter. For this project, I recommend setting the llm request_timeout parameter to 120 to reduce timeout errors when calling the OpenAI API.

Next, we will use the model to build character profiles for specific philosophers using information from the Stanford Encyclopedia of Philosophy (SEP), which is a free peer-reviewed resource.

As far as I know, the SEP does not have a publicly exposed API; but since we will be using exact names to find entries, we can write a script to make http requests to the SEP search engine, and then simply extract the first url from each result. From there, we can use the unstructured URL loader to load the entry text, chunk it, then create a vectorstore index with which the model can interact using a Q+A retriever.

Now we can engineer a prompt to build character profiles for each philosopher, which we will then use as system messages for the dialogue agents.

Naturally, we'll start with Plato and Aristotle.

These profiles contain more detail than what is strictly necessary for the dialogue agents to behave correctly; but in testing, I've found that having this extra detail does not adversely affect dialogue interactions and does open up more possibilities for creative experimentation with the agents.

Creating Dialogue Agents

Since the task here is essentially to create a role-playing scenario, we can closely adapt the Two-Player Dungeons & Dragon's simulation from the LangChain documentation.

The first step is to create a DialogueAgent class to store message history from the dialogue agent's point of view.

The next step is to create a DialogueSimulator class to control the speaker interactions.

Diverging from the D&D simulation in the LangChain docs, the next step is to create system messages, incorporating the character profiles for each philosopher, which will be used to instantiate the dialogue agents.

Finally, we create a function to run the simulation for n iterations, with a moderator and an objective for the dialogue. Then we are ready for Match #1!

Match #1: Plato vs. Aristotle

Topic: The Value of Poetry

Result: Aristotle Wins!

I've run this simulation many times, and, while there's some variation in the argumentation each time, there seems to be a deterministic arc to the exchange: Plato always puts up a bit of a fight at first and then always concedes to Aristotle that poetry indeed has value. Which makes sense: notwithstanding his views on poets in The Republic, Plato is himself undoubtedly one of the great literary figures of history.

Match #2: Hegel vs. Marx

Topic: Historical Materialism

Result: Hegel and Marx tie!

Repeated iterations of this simulation show that Marx and Hegel typically deadlock on this issue, with Marx sometimes managing to extract a few more materialist concessions from Hegel and Hegel sometimes remaining more steadfast in his idealism. This result also makes intuitive sense, as the two positions can be seen as inverses of one another. Marx famously wrote in a postscript to Capital that "with [Hegel], [the dialectic] is standing on its head. It must be inverted, in order to discover the rational kernel within the mystical shell."

Match #3: Bertrand Russell vs. Kurt Gödel

Topic: Foundations of Mathematics