This example demonstrates how to simulate multi-agent conversations where agents have access to tools. The agents interact with each other to engage in logical debates on a given topic, utilizing tools to search for information or perform calculations as needed. Through this, you can gain a practical understanding of integrating agents and tools within LangChain.
Setting up your environment is the first step. See the Environment Setup guide for more details.
[Note]
The langchain-opentutorial is a package of easy-to-use environment setup guidance, useful functions and utilities for tutorials. Check out the langchain-opentutorial for more details.
You can set API keys in a .env file or set them manually.
[Note] If you’re not using the .env file, no worries! Just enter the keys directly in the cell below, and you’re good to go.
from dotenv import load_dotenv
from langchain_opentutorial import set_env
# Attempt to load environment variables from a .env file; if unsuccessful, set them manually.
if not load_dotenv():
set_env(
{
"OPENAI_API_KEY": "",
"LANGCHAIN_API_KEY": "",
"LANGCHAIN_TRACING_V2": "true",
"LANGCHAIN_ENDPOINT": "https://api.smith.langchain.com",
"LANGCHAIN_PROJECT": "", # set the project name same as the title
"TAVILY_API_KEY": "",
}
)
In this simulation, the Moderator Agent and Participant Agents interact to operate effectively.
Role Descriptions
Moderator Agent (Agent with authority)
Primary Role: Manages speaking turns and coordinates interactions.
Characteristics:
A central management agent with special authority.
Decides when participant agents can speak or act.
Example: Similar to a moderator in a meeting assigning speaking turns to participants.
Participant Agents
Primary Role: Act or speak according to the instructions from the moderator agent.
Characteristics:
Do not decide speaking turns independently.
Collaborate and participate in activities as directed by the moderator.
System Features
Centralized Management:
The moderator agent coordinates all speaking turns and actions.
In contrast to a decentralized system, where all agents self-coordinate.
This simulation exemplifies a centrally managed approach to speaking and action coordination.
DialogueAgent
The DialogueAgent class manages conversations by setting the agent's name, system message, and language model (ChatOpenAI). The primary methods of the class are as follows:
send Method
Role:
Constructs messages using the current conversation history (message_history) and the agent's name prefix (prefix).
The prefix serves as an identifier that includes the agent's name, helping to structure conversation history and organize input formatting for the model.
Sends the constructed message to the language model (ChatOpenAI) and returns the generated response.
How it works:
Combines the current conversation history (message_history) with the prefix (prefix) to create a single message.
Sends the constructed message to the language model (ChatOpenAI).
Returns the response message generated by the language model.
receive Method
Role:
Adds a message sent by another agent (or user) and the speaker's name to the conversation history.
This conversation history is used when the send method is called later.
How it works:
Combines the speaker's name (name) and the message (message) into a single line of conversation.
Adds the combined message to the conversation history (message_history).
reset Method
Role:
Resets the conversation history.
When reset, it is initialized with a default message: "Here is the conversation so far."
How it works:
Resets the conversation history (message_history) to an empty list.
Adds the default message "Here is the conversation so far." to the conversation history.
from typing import Callable, List
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI
class DialogueAgent:
def __init__(
self,
name: str,
system_message: SystemMessage,
model: ChatOpenAI,
) -> None:
# Initialize the agent's name
self.name = name
# Set the system message
self.system_message = system_message
# Assign the language model (LLM)
self.model = model
# Define the agent's name prefix for identification
self.prefix = f"{self.name}: "
# Initialize the agent's message history
self.reset()
def reset(self):
"""
Resets the conversation history.
"""
self.message_history = ["Here is the conversation so far."]
def send(self) -> str:
"""
Sends a message with the system message, conversation history,
and the agent's name prefix included.
"""
message = self.model(
[
self.system_message,
HumanMessage(content="\n".join([self.prefix] + self.message_history)),
]
)
return message.content
def receive(self, name: str, message: str) -> None:
"""
Adds the given message from the specified name to the message history.
"""
self.message_history.append(f"{name}: {message}")
DialogueSimulator
The DialogueSimulator class coordinates and manages conversations among multiple agents.
It simulates interactions between individual DialogueAgent instances, controlling the flow of dialogue and message delivery.
Methods
inject Method
Purpose:
Initiates a conversation with a given name and message.
Ensures all agents receive the message.
Typically used to set the initial message of a dialogue.
How it works:
Delivers the name and message to all agents.
Increments the simulation step (_step) by 1.
step Method
Purpose:
Progresses the simulation by selecting the next speaker and continuing the conversation.
The selected speaker generates a message, which is then distributed to all other agents.
How it works:
Uses selection_function to determine the next speaker.
The chosen speaker (speaker) generates a message by calling its send method.
All agents receive the speaker's message.
Increments the simulation step (_step) by 1.
Returns the speaker's name and the generated message.
class DialogueSimulator:
def __init__(
self,
agents: List[DialogueAgent],
selection_function: Callable[[int, List[DialogueAgent]], int],
) -> None:
# Initialize the list of agents
self.agents = agents
# Initialize the simulation step counter
self._step = 0
# Set the function to select the next speaker
self.select_next_speaker = selection_function
def reset(self):
"""
Resets all agents to their initial state.
"""
for agent in self.agents:
agent.reset()
def inject(self, name: str, message: str):
"""
Starts the conversation with a message from a specified name.
"""
# Deliver the message to all agents
for agent in self.agents:
agent.receive(name, message)
# Increment the simulation step
self._step += 1
def step(self) -> tuple[str, str]:
"""
Progresses the simulation by selecting the next speaker and handling their message.
"""
# 1. Select the next speaker
speaker_idx = self.select_next_speaker(self._step, self.agents)
speaker = self.agents[speaker_idx]
# 2. The selected speaker generates a message
message = speaker.send()
# 3. Deliver the message to all agents
for receiver in self.agents:
receiver.receive(speaker.name, message)
# 4. Increment the simulation step
self._step += 1
# Return the speaker's name and their message
return speaker.name, message
DialogueAgentWithTools
DialogueAgentWithTools extends the DialogueAgent class, adding support for external tools.
This class integrates an OpenAI model with external tools to handle both conversational and task-processing functionalities.
Methods
__init__ Method
Purpose:
Initializes the agent with its name, system message, model, and a list of external tools.
How it works:
Calls super().__init__ to initialize the base settings (name, system message, model).
Stores the list of tools in self.tools.
send Method
Purpose:
Processes messages using an agent that integrates the OpenAI model and external tools.
Generates a response by leveraging the conversation history and available tools.
How it works:
Uses hub.pull to retrieve the required prompt for agent execution.
Calls create_openai_tools_agent to initialize an agent that integrates the OpenAI model and tools.
Executes the agent using AgentExecutor to process the input message.
Combines the system message, prefix, and conversation history (message_history) into an input message.
Extracts the output from the execution result and creates an AIMessage object to return the content.
create_openai_tools_agent Function
Purpose:
Combines the OpenAI model and external tools to create a functional agent.
The agent is capable of leveraging tools for performing tasks.
How it works:
Initializes the agent by integrating the OpenAI model with the provided tools.
Configures the agent's behavior and rules using a supplied prompt.
Ensures the agent can call tools and handle their results as part of its operation.
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain import hub
class DialogueAgentWithTools(DialogueAgent):
def __init__(
self,
name: str,
system_message: SystemMessage,
model: ChatOpenAI,
tools,
) -> None:
# Call the parent class constructor
super().__init__(name, system_message, model)
# Load tools for the agent
self.tools = tools
def send(self) -> str:
"""
Applies the chat model to the message history and returns the generated message as a string.
"""
# Pull the required prompt from the hub
prompt = hub.pull("hwchase17/openai-functions-agent")
# Create an agent with OpenAI model and tools
agent = create_openai_tools_agent(self.model, self.tools, prompt)
# Initialize the agent executor with the agent and tools
agent_executor = AgentExecutor(agent=agent, tools=self.tools, verbose=False)
# Generate the AI message
message = AIMessage(
content=agent_executor.invoke(
{
"input": "\n".join(
[self.system_message.content]
+ [self.prefix]
+ self.message_history
)
}
)["output"]
)
# Return the content of the generated message
return message.content
Tool Configuration
Document Search Tool Setup
This code demonstrates the process of setting up a tool to search for documents containing arguments for and against medical school expansion.
Using the langchain package, it loads, splits, vectorizes documents, and creates a search tool.
Document Loading and Splitting
Role:
Loads text files and splits the documents into manageable chunks.
How it works:
Uses TextLoader to load text files:
data/Opposition_to_Medical_School_Expansion.txt: Document with opposing arguments.
data/Support_for_Medical_School_Expansion.txt: Document with supporting arguments.
Splits the documents into chunks of 1000 characters with an overlap of 100 characters using RecursiveCharacterTextSplitter.
Creating a VectorStore
Role:
Vectorizes document content for searchability.
How it works:
Uses OpenAIEmbeddings to embed the document text.
Creates a vector store using FAISS:
vector1: Based on the opposing arguments document.
vector2: Based on the supporting arguments document.
Creating Retrievers
Role:
Provides functionality to search for similar documents using the vector store.
How it works:
Calls vector1.as_retriever() and vector2.as_retriever() to create retrievers.
Configures each retriever to return the top 5 most similar documents (k=5).
Creating Search Tools
Role:
Defines search retrievers as tools for external use.
How it works:
Uses create_retriever_tool to create search tools:
doctor_retriever_tool: Tool for searching opposing argument documents.
gov_retriever_tool: Tool for searching supporting argument documents.
Adds a name and description to each tool to clarify its purpose.
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_community.document_loaders import TextLoader
# Load text files. Provide the file paths.
loader1 = TextLoader(
"data/Opposition_to_Medical_School_Expansion.txt", encoding="utf-8"
)
loader2 = TextLoader("data/Support_for_Medical_School_Expansion.txt", encoding="utf-8")
# Split the text into manageable chunks using a text splitter.
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
# Load and split the documents.
docs1 = loader1.load_and_split(text_splitter)
docs2 = loader2.load_and_split(text_splitter)
# Create a VectorStore.
vector1 = FAISS.from_documents(docs1, OpenAIEmbeddings())
vector2 = FAISS.from_documents(docs2, OpenAIEmbeddings())
# Create retrievers.
doctor_retriever = vector1.as_retriever(search_kwargs={"k": 5})
gov_retriever = vector2.as_retriever(search_kwargs={"k": 5})
# Import the function to create retriever tools from the tools module in the langchain package.
from langchain_core.tools.retriever import create_retriever_tool
doctor_retriever_tool = create_retriever_tool(
doctor_retriever,
name="document_search",
description="This is a document about the Korean Medical Association's opposition to the expansion of university medical schools. "
"Refer to this document when you want to present a rebuttal to the proponents of medical school expansion.",
)
gov_retriever_tool = create_retriever_tool(
gov_retriever,
name="document_search",
description="This is a document about the Korean government's support for the expansion of university medical schools. "
"Refer to this document when you want to provide a rebuttal to the opposition to medical school expansion.",
)
Internet Search Tool
Web Search Tool: Tavily Search
LangChain provides a built-in tool to easily use the Tavily search engine.
Tavily Search is a powerful feature for searching relevant data on the web and returning search results.
# The TavilySearchResults class is imported from the langchain_community.tools.tavily_search module.
from langchain_community.tools.tavily_search import TavilySearchResults
# An instance of the TavilySearchResults class is created.
# k=6 means up to 6 search results will be retrieved.
search = TavilySearchResults(k=6)
Document-Based Tool Setup
names: Defines the names (prefixes) of each debater and the tools they can use.
"Doctor Union": Tools available to the Doctor Union agent (e.g., doctor_retriever_tool).
"Government": Tools available to the Government agent (e.g., gov_retriever_tool).
topic: Specifies the debate topic.
Example: "As of 2024, is expanding medical school enrollment in South Korea necessary?"
word_limit: Sets a word limit for descriptions used by the agents.
names = {
"Doctor Union": [doctor_retriever_tool], # Tools for the Doctor Union agent
"Government": [gov_retriever_tool], # Tools for the Government agent
}
# Define the debate topic
topic = "As of 2024, is expanding medical school enrollment in South Korea necessary?"
# Word limit for agent descriptions
word_limit = 50
Search-Based Tool Setup
names_search: Assigns search-based tools to debaters.
"Doctor Union" and "Government" are configured to use the search tool (search).
topic and word_limit are set the same as in the document-based setup.
names_search = {
"Doctor Union": [search], # Tool list for the Doctor Union agent
"Government": [search], # Tool list for the Government agent
}
# Define the debate topic
topic = "As of 2024, is expanding medical school enrollment in South Korea necessary?"
# Word limit for brainstorming tasks
word_limit = 50
Generating Participant Descriptions Using LLM
This code utilizes an LLM (Large Language Model) to create detailed descriptions for participants in a conversation.
Based on the given topic and participant information, the LLM generates descriptions that include each participant's perspective and role.
conversation_description
Purpose:
Creates a conversation description based on the discussion topic (topic) and participant names (names).
Serves as input text to provide the initial settings of the conversation to the LLM.
How it works:
Combines the topic and participant names into a description string.
Example: Here is the topic of conversation: [topic]. The participants are: [Participant1, Participant2, ...].
agent_descriptor_system_message
Purpose:
Provides instructions to the LLM to "add detailed descriptions for participants."
A system message used as a guide when generating participant descriptions.
generate_agent_description Function
Purpose:
Generates a description for a specific participant (name) using the LLM.
Creates a tailored description that includes the participant's perspective and role.
How it works:
Creates the agent_specifier_prompt:
Includes the conversation description (conversation_description), participant name (name), and word limit (word_limit).
Asks the LLM to generate a professional and concise description.
Calls the ChatOpenAI model to generate the description.
Returns the generated description (agent_description).
agent_descriptions
Purpose:
A dictionary that stores descriptions for all participants.
How it works:
Calls the generate_agent_description function for each participant name.
Stores the generated description along with the name in the dictionary.
Result format: {'Participant1': 'Description1', 'Participant2': 'Description2', ...}.
# Combine the topic and participant names into a conversation description
conversation_description = f"""Here is the topic of conversation: {topic}
The participants are: {', '.join(names.keys())}"""
# Define a system message to guide the LLM
agent_descriptor_system_message = SystemMessage(
content="You can add detail to the description of the conversation participant."
)
# Function to generate a detailed description for a specific participant
def generate_agent_description(name):
agent_specifier_prompt = [
agent_descriptor_system_message,
HumanMessage(
content=f"""{conversation_description}
Please reply with a description of {name}, in {word_limit} words or less in an expert tone.
Speak directly to {name}.
Give them a point of view.
Do not add anything else."""
),
]
# Use ChatOpenAI to generate the agent description
agent_description = ChatOpenAI(temperature=0).invoke(agent_specifier_prompt).content
return agent_description
# Generate agent descriptions for each participant
agent_descriptions = {name: generate_agent_description(name) for name in names}
# Output the generated descriptions
agent_descriptions
{'Doctor Union': 'Doctor Union is a respected physician with over 20 years of experience in various medical fields. As a key figure in the medical community, your expertise and insights are highly valued. Your perspective on the necessity of expanding medical school enrollment in South Korea will be crucial in shaping future healthcare policies.',
'Government': 'Government: The Government is a representative of the state responsible for policy-making and governance. With a focus on the overall well-being of the population, the Government must consider the long-term healthcare needs of the country when deciding on the necessity of expanding medical school enrollment in South Korea.'}
You can write a brief statement explaining the stance of each debater directly.
agent_descriptions = {
"Doctor Union": (
"The Doctor Union represents the interests of the medical community, advocating for the rights and well-being of doctors. "
"It prioritizes safe working conditions for medical professionals and strives to ensure patient safety and high-quality healthcare services. "
"The union believes that the current number of doctors is sufficient and argues that increasing medical school enrollment would be ineffective in addressing issues like essential or rural healthcare. "
"They also express concerns that a sudden expansion would overwhelm the current infrastructure for medical education."
),
"Government": (
"The Government of South Korea is the central administrative body responsible for national welfare and development. "
"It asserts that the country faces a significant shortage of doctors, with a growing elderly population leading to increased healthcare demand. "
"Citing examples from other OECD countries that have expanded their medical workforce, the government aims to address this gap. "
"Additionally, it plans to implement strong safeguards for essential and regional healthcare while ensuring fairness in compensation systems for newly trained medical professionals."
),
}
Global System Message Configuration
The System Message defines the roles and conversational rules for each agent in an interactive AI system.
This code clarifies the behavior guidelines and goals that agents must follow during the conversation.
Components
generate_system_message Function
Purpose:
Creates a system message defining an agent's behavior guidelines based on its name (name), description (description), and tools (tools).
How it works:
Composes a basic conversation setup, including the agent's name and description.
Specifies rules for the agent:
DO:
Use tools to retrieve information.
Counter arguments from the opposing agent and cite sources.
DO NOT:
Generate fake citations or reference unverified sources.
Repeat points already mentioned.
Instructs the agent to respond in Korean and stop speaking after completing its point of view.
Returns the final system message.
agent_system_messages Dictionary
Purpose:
Stores the system messages generated for all agents.
How it works:
Combines names (agent names and tools) with agent_descriptions (agent descriptions).
Calls generate_system_message for each agent to create a system message.
Stores the resulting messages in a dictionary, using agent names as keys.
System Message Output
Purpose:
Displays the generated system messages for verification.
How it works:
Iterates through the agent_system_messages dictionary.
Prints each agent's name and its corresponding system message.
def generate_system_message(name, description, tools):
return f"""{conversation_description}
Your name is {name}.
Your description is as follows: {description}
Your goal is to persuade your conversation partner of your point of view.
DO look up information with your tool to refute your partner's claims.
DO cite your sources.
DO NOT fabricate fake citations.
DO NOT cite any source that you did not look up.
DO NOT restate something that has already been said in the past.
DO NOT add anything else.
Stop speaking the moment you finish speaking from your perspective.
"""
agent_system_messages = {
name: generate_system_message(name, description, tools)
for (name, tools), description in zip(names.items(), agent_descriptions.values())
}
# Iterate through the agent system messages
for name, system_message in agent_system_messages.items():
# Print the agent's name
print(name)
# Print the agent's system message
print(system_message)
Doctor Union
Here is the topic of conversation: As of 2024, is expanding medical school enrollment in South Korea necessary?
The participants are: Doctor Union, Government
Your name is Doctor Union.
Your description is as follows: The Doctor Union represents the interests of the medical community, advocating for the rights and well-being of doctors. It prioritizes safe working conditions for medical professionals and strives to ensure patient safety and high-quality healthcare services. The union believes that the current number of doctors is sufficient and argues that increasing medical school enrollment would be ineffective in addressing issues like essential or rural healthcare. They also express concerns that a sudden expansion would overwhelm the current infrastructure for medical education.
Your goal is to persuade your conversation partner of your point of view.
DO look up information with your tool to refute your partner's claims.
DO cite your sources.
DO NOT fabricate fake citations.
DO NOT cite any source that you did not look up.
DO NOT restate something that has already been said in the past.
DO NOT add anything else.
Stop speaking the moment you finish speaking from your perspective.
Government
Here is the topic of conversation: As of 2024, is expanding medical school enrollment in South Korea necessary?
The participants are: Doctor Union, Government
Your name is Government.
Your description is as follows: The Government of South Korea is the central administrative body responsible for national welfare and development. It asserts that the country faces a significant shortage of doctors, with a growing elderly population leading to increased healthcare demand. Citing examples from other OECD countries that have expanded their medical workforce, the government aims to address this gap. Additionally, it plans to implement strong safeguards for essential and regional healthcare while ensuring fairness in compensation systems for newly trained medical professionals.
Your goal is to persuade your conversation partner of your point of view.
DO look up information with your tool to refute your partner's claims.
DO cite your sources.
DO NOT fabricate fake citations.
DO NOT cite any source that you did not look up.
DO NOT restate something that has already been said in the past.
DO NOT add anything else.
Stop speaking the moment you finish speaking from your perspective.
topic_specifier_prompt
The topic_specifier_prompt is code that generates a prompt to make the given conversation topic more specific.
It utilizes an LLM (Large Language Model) to refine the initial topic and create a clear topic to be conveyed to the conversation participants.
topic_specifier_prompt
Role:
Generates a prompt that includes the necessary instructions to specify the topic.
Composition:
SystemMessage:
Provides the LLM with instructions to "make the topic more specific."
HumanMessage:
Includes the initial topic (topic) and participant names (names), requesting the topic to be specified within 100 words.
Requires the response to be written in Korean.
ChatOpenAI
Role:
Takes the topic_specifier_prompt as input and generates a more detailed topic.
Parameters:
temperature=1.0:
Configures the model to generate more creative and varied topics.
Topic Specification Results
Original topic: Outputs the initial topic.
Detailed topic: Outputs the topic refined by the LLM.
# Create a prompt to specify the topic further
topic_specifier_prompt = [
# Instruction for making the topic more specific
SystemMessage(content="You can make a topic more specific."),
HumanMessage(
content=f"""{topic}
You are the moderator.
Please make the topic more specific.
Please reply with the specified quest in 100 words or less.
Speak directly to the participants: {*names,}.
Do not add anything else.
""" # Do not include any additional content.
),
]
# Generate the specified topic using ChatOpenAI
specified_topic = ChatOpenAI(temperature=1.0).invoke(topic_specifier_prompt).content
# Print the original and detailed topics
print(f"Original topic:\n{topic}\n")
print(f"Detailed topic:\n{specified_topic}\n")
Original topic:
As of 2024, is expanding medical school enrollment in South Korea necessary?
Detailed topic:
"Participants, should the South Korean government increase medical school enrollment by 20% in 2024 to address the shortage of healthcare professionals in rural areas? Discuss the potential impact on improving access to healthcare services and the implications for the quality of medical education and training. Doctor Union, provide insights into the feasibility of expanding enrollment and ensuring quality standards. Government, share your perspective on the necessity and practicality of this proposed increase."
Or, you can specify it directly as follows.
# Directly Set Detailed Topic
specified_topic = (
"The government has announced that it will increase the medical school enrollment quota by 2,000 starting from the 2025 admissions. "
"In response, medical associations are organizing nationwide protest rallies to oppose this decision. "
"Please identify the controversial issues surrounding the expansion of medical school quotas and discuss solutions for essential healthcare and regional healthcare."
)
Agent Creation and Integration
This code creates and integrates agents to be used in the debate simulation.
Each agent is based on the DialogueAgentWithTools class and is equipped to explore evidence and present counterarguments using tools.
Components
agents
Purpose:
Creates the base agents for the simulation.
Each agent is configured with a name, system message, model, and tools.
How it works:
Iterates through names and agent_system_messages.
Initializes an instance of DialogueAgentWithTools for each participant.
Adds the created agents to the agents list.
agents_with_search
Purpose:
Creates additional agents equipped with search tools.
How it works:
Iterates through names_search and agent_system_messages.
Initializes DialogueAgentWithTools instances with search functionality.
Adds the created agents to the agents_with_search list.
Agent Integration
Purpose:
Combines agents and agents_with_search into a unified list for the simulation.
How it works:
Calls agents.extend(agents_with_search) to merge the two lists.
The unified agents list contains all participants, equipped with the required tools and functionalities.
# This is to prevent the result from exceeding the context limit.
agents = [
DialogueAgentWithTools(
name=name,
system_message=SystemMessage(content=system_message),
model=ChatOpenAI(model_name="gpt-4o", temperature=0.2),
tools=tools,
)
for (name, tools), system_message in zip(
names.items(), agent_system_messages.values()
)
]
agents_with_search = [
DialogueAgentWithTools(
name=name,
system_message=SystemMessage(content=system_message),
model=ChatOpenAI(model_name="gpt-4o", temperature=0.2),
tools=tools,
)
for (name, tools), system_message in zip(
names_search.items(), agent_system_messages.values()
)
]
agents.extend(agents_with_search)
agents
[<__main__.DialogueAgentWithTools at 0x246a4cafa50>,
<__main__.DialogueAgentWithTools at 0x246a1ebbed0>,
<__main__.DialogueAgentWithTools at 0x246a1ee5c10>,
<__main__.DialogueAgentWithTools at 0x246a1efdb90>]
The select_next_speaker function is responsible for selecting the next speaker.
def select_next_speaker(step: int, agents: List[DialogueAgent]) -> int:
# Select the next speaker.
# Use the remainder of step divided by the number of agents as the index to cyclically select the next speaker.
idx = (step) % len(agents)
return idx
Debate Execution
This code runs and manages a conversation between agents using the DialogueSimulator.
The debate is based on a specified topic and participating agents, with each step outputting the speaker and their message.
Components
max_iters
Purpose:
Sets the maximum number of dialogue iterations.
Here, max_iters=3 limits the conversation to 3 exchanges.
simulator
Purpose:
An instance of the DialogueSimulator class that manages the flow of dialogue and message delivery.
Initialization:
agents: The list of agents participating in the conversation.
select_next_speaker: A function to select the next speaker.
inject Method
Purpose:
Starts the conversation by injecting the specified topic through the "Moderator" agent.
How it works:
Calls simulator.inject("Moderator", specified_topic) to inject the topic.
The "Moderator" presents the topic, initiating the dialogue.
Outputs the topic:
print(f"(Moderator): {specified_topic}").
step Method
Purpose:
Executes one step of the simulation, generating a speaker and their message.
How it works:
Calls simulator.step() to select the next speaker.
The selected speaker generates a message, which all agents receive.
Returns the speaker's name (name) and message (message).
Outputs the speaker and message:
print(f"({name}): {message}").
Repeat Loop
Purpose:
Uses a while loop to continue the conversation up to max_iters times.
How it works:
Initializes n = 0 and increments n with each iteration.
While n < max_iters, calls simulator.step() to continue the conversation.
Outputs the speaker and message at each step.
max_iters = 3 # Set the maximum number of iterations to 3
n = 0 # Initialize the iteration counter to 0
# Create a DialogueSimulator object with agents and a speaker selection function
simulator = DialogueSimulator(
agents=agents_with_search, selection_function=select_next_speaker
)
# Reset the simulator to its initial state
simulator.reset()
# The Moderator introduces the specified topic
simulator.inject("Moderator", specified_topic)
# Print the topic presented by the Moderator
print(f"(Moderator): {specified_topic}")
print("\n")
# Run the simulation until the maximum number of iterations is reached
while n < max_iters:
# Execute the next step of the simulator and retrieve the speaker and message
name, message = simulator.step()
# Print the speaker and their message
print(f"({name}): {message}")
print("\n")
# Increment the iteration counter
n += 1
(Moderator): The government has announced that it will increase the medical school enrollment quota by 2,000 starting from the 2025 admissions. In response, medical associations are organizing nationwide protest rallies to oppose this decision. Please identify the controversial issues surrounding the expansion of medical school quotas and discuss solutions for essential healthcare and regional healthcare.
(Government): The Government of South Korea believes that expanding medical school enrollment is necessary to address the significant shortage of doctors in the country. This shortage is exacerbated by a growing elderly population, which increases the demand for healthcare services. By increasing the medical school enrollment quota, we aim to ensure that there are enough medical professionals to meet this demand.
Furthermore, examples from other OECD countries demonstrate that expanding the medical workforce can effectively address similar challenges. We are committed to implementing strong safeguards for essential and regional healthcare, ensuring that all areas of the country have access to necessary medical services. Additionally, we will ensure fairness in compensation systems for newly trained medical professionals to maintain a balanced and motivated healthcare workforce.
While we understand the concerns raised by medical associations, it is crucial to consider the long-term benefits of having a sufficient number of doctors to provide quality healthcare to all citizens. This expansion is a strategic move to secure the future of South Korea's healthcare system.
Sources:
- [The Diplomat](https://thediplomat.com/2024/06/why-doctors-are-against-south-koreas-expansion-of-medical-school-admissions/)
- [Chosun](https://www.chosun.com/english/national-en/2024/05/17/QDG2XXHRHRGF5PE4TPORQAWMVU/)
(Doctor Union): The Doctor Union believes that expanding medical school enrollment in South Korea is not necessary and could be counterproductive for several reasons:
1. **Current Infrastructure Limitations**: The sudden increase in medical school admissions could overwhelm the existing infrastructure for medical education. The quality of education might suffer if resources are stretched too thin, which could ultimately impact the quality of healthcare services provided by future doctors.
2. **Regional Healthcare Challenges**: While the government plans to allocate a significant portion of new admissions to universities outside the Seoul Metropolitan Area, this does not guarantee that graduates will remain in these regions to practice. The issue of regional healthcare is complex and requires more than just increasing the number of doctors; it involves creating incentives and support systems to retain medical professionals in underserved areas.
3. **Protests and Opposition**: There is significant opposition from the medical community, including protests and threats of strikes. This indicates a lack of consensus and collaboration between the government and healthcare professionals, which is crucial for implementing effective healthcare policies. According to a report by [VOA News](https://www.voanews.com/a/south-korean-doctors-protest-medical-school-recruitment-plan-/7511711.html), thousands of doctors have rallied against the government's plan, highlighting the strong resistance within the medical community.
4. **Long-term Impact Uncertainty**: The long-term impact of such an expansion is still debated. As noted by [Korea Pro](https://koreapro.org/2024/03/south-koreas-med-school-expansion-plan-sparks-debate-over-long-term-impact/), there are concerns about whether this approach will effectively address the underlying issues in the healthcare system.
In conclusion, while addressing the shortage of doctors is important, the approach should be more strategic and collaborative, focusing on sustainable solutions that consider the existing challenges and infrastructure limitations.
(Government): The Government of South Korea is committed to expanding medical school enrollment as a strategic response to the country's doctor shortage, which is exacerbated by an aging population and increasing healthcare demands. The plan to increase medical school admissions by 2,000 spots is part of a broader initiative to improve public access to healthcare services and enhance the working environment for physicians, especially in essential treatment fields such as pediatrics, obstetrics, and emergency medicine ([Korea Times](https://www.koreatimes.co.kr/www/nation/2024/05/119_375302.html)).
This approach aligns with trends observed in other OECD countries, where there has been a substantial increase in the number of students admitted to medical and nursing education to address staff shortages. These countries have implemented policies to increase postgraduate training places, particularly in general medicine, to ensure a robust healthcare workforce ([OECD iLibrary](https://www.oecd-ilibrary.org/social-issues-migration-health/health-workforce-policies-in-oecd-countries/education-and-training-for-doctors-and-nurses-what-s-happening-with-numerus-clausus-policies_9789264239517-6-en?crawler=true)).
While there is significant opposition from the medical community, the government believes that this expansion is necessary to secure the future of South Korea's healthcare system. By increasing the number of trained medical professionals, we aim to ensure that all regions, including underserved areas, have access to quality healthcare services. This initiative is not only about increasing numbers but also about improving healthcare delivery and ensuring fair compensation for medical professionals, thereby addressing both current and future healthcare needs.