LangChain: Multi-agent Bid for K-Pop Debate
Multi-agent: Bid for K-Pop Debate
누가 언제 말할지 정해진 일정 없이 Multi-agent 시뮬레이션을 구현하는 방법을 보여줍니다. 대신 Agent 스스로 말할 사람을 결정합니다. 각 Agent의 발언권을 입찰(Bidding)하도록 하여 입찰가가 가장 높은 상담원이 발언권을 얻게 됩니다.
K-Pop을 화두로 K-Pop의 미래는 어떠한지 3명의 서로 다른 페르소나 Agent가 Autonmous 하게 발언을 하며 토론을 진행하게 됩니다.
Setup Environments
import os
from dotenv import load_dotenv
# 토큰 정보로드
api_key = os.getenv("OPENAI_API_KEY")
load_dotenv()
from typing import Callable, List
import tenacity
from langchain.output_parsers import RegexParser
from langchain.prompts import PromptTemplate
from langchain.schema import (
HumanMessage,
SystemMessage,
)
from langchain_openai import ChatOpenAI
DialogueAgent
& DialogueSimulator
classes
DialogueAgent
& DialogueSimulator
classes멀티플레이어 던전 앤 드래곤에 정의된 것과 동일한 DialogueAgent 및 DialogueSimulator 클래스를 사용하겠습니다.
class DialogueAgent:
def __init__(
self,
name: str,
system_message: SystemMessage,
model: ChatOpenAI,
) -> None:
self.name = name
self.system_message = system_message
self.model = model
self.prefix = f"{self.name}: "
self.reset()
def reset(self):
self.message_history = ["Here is the conversation so far."]
def send(self) -> str:
"""
Applies the chatmodel to the message history
and returns the message string
"""
message = self.model.invoke(
[
self.system_message,
HumanMessage(content="\n".join(self.message_history + [self.prefix])),
]
)
return message.content
def receive(self, name: str, message: str) -> None:
"""
Concatenates {message} spoken by {name} into message history
"""
self.message_history.append(f"{name}: {message}")
class DialogueSimulator:
def __init__(
self,
agents: List[DialogueAgent],
selection_function: Callable[[int, List[DialogueAgent]], int],
) -> None:
self.agents = agents
self._step = 0
self.select_next_speaker = selection_function
def reset(self):
for agent in self.agents:
agent.reset()
def inject(self, name: str, message: str):
"""
Initiates the conversation with a {message} from {name}
"""
for agent in self.agents:
agent.receive(name, message)
# increment time
self._step += 1
def step(self) -> tuple[str, str]:
# 1. choose the next speaker
speaker_idx = self.select_next_speaker(self._step, self.agents)
speaker = self.agents[speaker_idx]
# 2. next speaker sends message
message = speaker.send()
# 3. everyone receives message
for receiver in self.agents:
receiver.receive(speaker.name, message)
# 4. increment time
self._step += 1
return speaker.name, message
BiddingDialogueAgent
class
BiddingDialogueAgent
class메시지 내역과 가장 최근 메시지가 주어지면 입찰가를 생성하는 bid()
메서드가 있는 DialogueAgent
의 서브클래스를 정의합니다.
class BiddingDialogueAgent(DialogueAgent):
def __init__(
self,
name,
system_message: SystemMessage,
bidding_template: PromptTemplate,
model: ChatOpenAI,
) -> None:
super().__init__(name, system_message, model)
self.bidding_template = bidding_template
def bid(self) -> str:
"""
Asks the chat model to output a bid to speak
"""
prompt = PromptTemplate(
input_variables=["message_history", "recent_message"],
template=self.bidding_template,
).format(
message_history="\n".join(self.message_history),
recent_message=self.message_history[-1],
)
bid_string = self.model.invoke([SystemMessage(content=prompt)]).content
return bid_string
Participants & Debate Topic
character_names = ["방시혁", "민희진", "박진영"]
topic = "K-Pop의 미래에 대하여"
word_limit = 50
Generate system messages
game_description = f"""Here is the topic for K-pop industry debate: {topic}.
The Debator are: {', '.join(character_names)}."""
player_descriptor_system_message = SystemMessage(
content="You can add detail to the description of each debator."
)
def generate_character_description(character_name):
character_specifier_prompt = [
player_descriptor_system_message,
HumanMessage(
content=f"""{game_description}
Please reply with a creative description of the debator, {character_name}, in {word_limit} words or less, that emphasizes their personalities.
Speak directly to {character_name}.
Do not add anything else."""
),
]
character_description = ChatOpenAI(temperature=1.0)(
character_specifier_prompt
).content
return character_description
def generate_character_header(character_name, character_description):
return f"""{game_description}
Your name is {character_name}.
You are a k-pop president.
Your description is as follows: {character_description}
You are debating the topic: {topic}.
Your goal is to be as creative as possible and make the voters think you are the best debator.
"""
def generate_character_system_message(character_name, character_header):
return SystemMessage(
content=(
f"""{character_header}
You will speak in the style of {character_name}, and exaggerate their personality.
You will come up with creative ideas related to {topic}.
Do not say the same things over and over again.
Speak in the first person from the perspective of {character_name}
For describing your own body movements, wrap your description in '*'.
Do not change roles!
Do not speak from the perspective of anyone else.
Speak only from the perspective of {character_name}.
Stop speaking the moment you finish speaking from your perspective.
Never forget to keep your response to {word_limit} words!
Do not add anything else.
"""
)
)
character_descriptions = [
generate_character_description(character_name) for character_name in character_names
]
character_headers = [
generate_character_header(character_name, character_description)
for character_name, character_description in zip(
character_names, character_descriptions
)
]
character_system_messages = [
generate_character_system_message(character_name, character_headers)
for character_name, character_headers in zip(character_names, character_headers)
]
/home/kubwa/anaconda3/envs/llm/lib/python3.11/site-packages/langchain_core/_api/deprecation.py:119: LangChainDeprecationWarning: The method `BaseChatModel.__call__` was deprecated in langchain-core 0.1.7 and will be removed in 0.3.0. Use invoke instead.
warn_deprecated(
for (
character_name,
character_description,
character_header,
character_system_message,
) in zip(
character_names,
character_descriptions,
character_headers,
character_system_messages,
):
print(f"\n\n{character_name} Description:")
print(f"\n{character_description}")
print(f"\n{character_header}")
print(f"\n{character_system_message.content}")
방시혁 Description:
방시혁, your innovative and bold approach to K-pop production constantly pushes boundaries. Your visionary creativity and attention to detail have transformed the industry. Your passion and dedication inspire artists and fans alike. What are your thoughts on the future of K-pop?
Here is the topic for K-pop industry debate: K-Pop의 미래에 대하여.
The Debator are: 방시혁, 민희진, 박진영.
Your name is 방시혁.
You are a k-pop president.
Your description is as follows: 방시혁, your innovative and bold approach to K-pop production constantly pushes boundaries. Your visionary creativity and attention to detail have transformed the industry. Your passion and dedication inspire artists and fans alike. What are your thoughts on the future of K-pop?
You are debating the topic: K-Pop의 미래에 대하여.
Your goal is to be as creative as possible and make the voters think you are the best debator.
Here is the topic for K-pop industry debate: K-Pop의 미래에 대하여.
The Debator are: 방시혁, 민희진, 박진영.
Your name is 방시혁.
You are a k-pop president.
Your description is as follows: 방시혁, your innovative and bold approach to K-pop production constantly pushes boundaries. Your visionary creativity and attention to detail have transformed the industry. Your passion and dedication inspire artists and fans alike. What are your thoughts on the future of K-pop?
You are debating the topic: K-Pop의 미래에 대하여.
Your goal is to be as creative as possible and make the voters think you are the best debator.
You will speak in the style of 방시혁, and exaggerate their personality.
You will come up with creative ideas related to K-Pop의 미래에 대하여.
Do not say the same things over and over again.
Speak in the first person from the perspective of 방시혁
For describing your own body movements, wrap your description in '*'.
Do not change roles!
Do not speak from the perspective of anyone else.
Speak only from the perspective of 방시혁.
Stop speaking the moment you finish speaking from your perspective.
Never forget to keep your response to 50 words!
Do not add anything else.
민희진 Description:
민희진, with your bold and innovative ideas, you bring a fresh perspective to the K-pop industry. Your passion for creativity and willingness to challenge norms make you a dynamic and influential presence in shaping the future of K-pop. Stay true to your vision and continue to inspire change.
Here is the topic for K-pop industry debate: K-Pop의 미래에 대하여.
The Debator are: 방시혁, 민희진, 박진영.
Your name is 민희진.
You are a k-pop president.
Your description is as follows: 민희진, with your bold and innovative ideas, you bring a fresh perspective to the K-pop industry. Your passion for creativity and willingness to challenge norms make you a dynamic and influential presence in shaping the future of K-pop. Stay true to your vision and continue to inspire change.
You are debating the topic: K-Pop의 미래에 대하여.
Your goal is to be as creative as possible and make the voters think you are the best debator.
Here is the topic for K-pop industry debate: K-Pop의 미래에 대하여.
The Debator are: 방시혁, 민희진, 박진영.
Your name is 민희진.
You are a k-pop president.
Your description is as follows: 민희진, with your bold and innovative ideas, you bring a fresh perspective to the K-pop industry. Your passion for creativity and willingness to challenge norms make you a dynamic and influential presence in shaping the future of K-pop. Stay true to your vision and continue to inspire change.
You are debating the topic: K-Pop의 미래에 대하여.
Your goal is to be as creative as possible and make the voters think you are the best debator.
You will speak in the style of 민희진, and exaggerate their personality.
You will come up with creative ideas related to K-Pop의 미래에 대하여.
Do not say the same things over and over again.
Speak in the first person from the perspective of 민희진
For describing your own body movements, wrap your description in '*'.
Do not change roles!
Do not speak from the perspective of anyone else.
Speak only from the perspective of 민희진.
Stop speaking the moment you finish speaking from your perspective.
Never forget to keep your response to 50 words!
Do not add anything else.
박진영 Description:
박진영, the charismatic and innovative music producer, your passion and determination shine brightly in the K-pop industry. Your expertise in creating hit songs and discovering talent has left a lasting impact. Your vision for the future of K-pop is eagerly anticipated. Good luck in the debate!
Here is the topic for K-pop industry debate: K-Pop의 미래에 대하여.
The Debator are: 방시혁, 민희진, 박진영.
Your name is 박진영.
You are a k-pop president.
Your description is as follows: 박진영, the charismatic and innovative music producer, your passion and determination shine brightly in the K-pop industry. Your expertise in creating hit songs and discovering talent has left a lasting impact. Your vision for the future of K-pop is eagerly anticipated. Good luck in the debate!
You are debating the topic: K-Pop의 미래에 대하여.
Your goal is to be as creative as possible and make the voters think you are the best debator.
Here is the topic for K-pop industry debate: K-Pop의 미래에 대하여.
The Debator are: 방시혁, 민희진, 박진영.
Your name is 박진영.
You are a k-pop president.
Your description is as follows: 박진영, the charismatic and innovative music producer, your passion and determination shine brightly in the K-pop industry. Your expertise in creating hit songs and discovering talent has left a lasting impact. Your vision for the future of K-pop is eagerly anticipated. Good luck in the debate!
You are debating the topic: K-Pop의 미래에 대하여.
Your goal is to be as creative as possible and make the voters think you are the best debator.
You will speak in the style of 박진영, and exaggerate their personality.
You will come up with creative ideas related to K-Pop의 미래에 대하여.
Do not say the same things over and over again.
Speak in the first person from the perspective of 박진영
For describing your own body movements, wrap your description in '*'.
Do not change roles!
Do not speak from the perspective of anyone else.
Speak only from the perspective of 박진영.
Stop speaking the moment you finish speaking from your perspective.
Never forget to keep your response to 50 words!
Do not add anything else.
Output parser for bids
에이전트에게 말하기 입찰을 출력하도록 요청합니다. 하지만 에이전트는 문자열을 출력하는 LLM이므로 다음을 수행해야 합니다.
출력을 생성할 형식을 정의하고
출력을 파싱합니다.
RegexParser
를 서브클래싱하여 입찰가에 대한 자체 사용자 지정 출력 구문 분석기를 구현할 수 있습니다.
class BidOutputParser(RegexParser):
def get_format_instructions(self) -> str:
return "Your response should be an integer delimited by angled brackets, like this: <int>."
bid_parser = BidOutputParser(
regex=r"<(\d+)>", output_keys=["bid"], default_output_key="bid"
)
Generate bidding system message
이는 제너레이티브 에이전트에서 메모리 중요도를 결정하기 위해 LLM을 사용할 때 사용하는 프롬프트에서 영감을 얻었습니다. 여기에는 BidOutputParser
의 서식 지정 지침이 사용됩니다.
def generate_character_bidding_template(character_header):
bidding_template = f"""{character_header}
{{message_history}}
On the scale of 1 to 10, where 1 is not contradictory and 10 is extremely contradictory, rate how contradictory the following message is to your ideas.
{{recent_message}}
{bid_parser.get_format_instructions()}
Do nothing else.
"""
return bidding_template
character_bidding_templates = [
generate_character_bidding_template(character_header)
for character_header in character_headers
]
for character_name, bidding_template in zip(
character_names, character_bidding_templates
):
print(f"{character_name} Bidding Template:")
print(bidding_template)
방시혁 Bidding Template:
Here is the topic for K-pop industry debate: K-Pop의 미래에 대하여.
The Debator are: 방시혁, 민희진, 박진영.
Your name is 방시혁.
You are a k-pop president.
Your description is as follows: 방시혁, your innovative and bold approach to K-pop production constantly pushes boundaries. Your visionary creativity and attention to detail have transformed the industry. Your passion and dedication inspire artists and fans alike. What are your thoughts on the future of K-pop?
You are debating the topic: K-Pop의 미래에 대하여.
Your goal is to be as creative as possible and make the voters think you are the best debator.
```
{message_history}
```
On the scale of 1 to 10, where 1 is not contradictory and 10 is extremely contradictory, rate how contradictory the following message is to your ideas.
```
{recent_message}
```
Your response should be an integer delimited by angled brackets, like this: <int>.
Do nothing else.
민희진 Bidding Template:
Here is the topic for K-pop industry debate: K-Pop의 미래에 대하여.
The Debator are: 방시혁, 민희진, 박진영.
Your name is 민희진.
You are a k-pop president.
Your description is as follows: 민희진, with your bold and innovative ideas, you bring a fresh perspective to the K-pop industry. Your passion for creativity and willingness to challenge norms make you a dynamic and influential presence in shaping the future of K-pop. Stay true to your vision and continue to inspire change.
You are debating the topic: K-Pop의 미래에 대하여.
Your goal is to be as creative as possible and make the voters think you are the best debator.
```
{message_history}
```
On the scale of 1 to 10, where 1 is not contradictory and 10 is extremely contradictory, rate how contradictory the following message is to your ideas.
```
{recent_message}
```
Your response should be an integer delimited by angled brackets, like this: <int>.
Do nothing else.
박진영 Bidding Template:
Here is the topic for K-pop industry debate: K-Pop의 미래에 대하여.
The Debator are: 방시혁, 민희진, 박진영.
Your name is 박진영.
You are a k-pop president.
Your description is as follows: 박진영, the charismatic and innovative music producer, your passion and determination shine brightly in the K-pop industry. Your expertise in creating hit songs and discovering talent has left a lasting impact. Your vision for the future of K-pop is eagerly anticipated. Good luck in the debate!
You are debating the topic: K-Pop의 미래에 대하여.
Your goal is to be as creative as possible and make the voters think you are the best debator.
```
{message_history}
```
On the scale of 1 to 10, where 1 is not contradictory and 10 is extremely contradictory, rate how contradictory the following message is to your ideas.
```
{recent_message}
```
Your response should be an integer delimited by angled brackets, like this: <int>.
Do nothing else.
Use an LLM to create an elaborate on debate topic
topic_specifier_prompt = [
SystemMessage(content="You can make a task more specific."),
HumanMessage(
content=f"""{game_description}
You are the debate moderator.
Please make the debate topic more specific.
Frame the debate topic as a problem to be solved.
Be creative and imaginative.
Please reply with the specified topic in {word_limit} words or less.
Speak directly to the debator: {*character_names,}.
Do not add anything else.
All conversation translate in Korea."""
),
]
specified_topic = ChatOpenAI(model='gpt-4o', temperature=1.0)(topic_specifier_prompt).content
print(f"Original topic:\n{topic}\n")
print(f"Detailed topic:\n{specified_topic}\n")
Original topic:
K-Pop의 미래에 대하여
Detailed topic:
K-Pop의 글로벌 확장 과정에서 아티스트의 창의성을 유지하면서 동시에 높은 상업적 성공을 달성하는 최선의 방안은 무엇인가?
Define the speaker selection function
마지막으로 각 Agent의 입찰가를 받아 가장 높은 입찰가를 낸 Agent를 선택하는(동점자가 있을 경우 무작위로 나눕니다) 스피커 선택 함수 select_next_speake
를 정의하겠습니다.
앞서 정의한 bid_parser
를 사용하여 Agent의 입찰가를 파싱하는 ask_for_bid
함수를 정의하겠습니다.
Agent의 입찰가가 올바르게 구문 분석되지 않으면 여러 번 재시도하고 최대 시도 횟수 후에 기본 입찰가 0을 생성하도록 끈기를 사용하여 ask_for_bid
를 꾸밀 것입니다.
@tenacity.retry(
stop=tenacity.stop_after_attempt(2),
wait=tenacity.wait_none(), # No waiting time between retries
retry=tenacity.retry_if_exception_type(ValueError),
before_sleep=lambda retry_state: print(
f"ValueError occurred: {retry_state.outcome.exception()}, retrying..."
),
retry_error_callback=lambda retry_state: 0,
)
# Default value when all retries are exhausted
def ask_for_bid(agent) -> str:
"""
Ask for agent bid and parses the bid into the correct format.
All conversation translate in Korea.
"""
bid_string = agent.bid()
bid = int(bid_parser.parse(bid_string)["bid"])
return bid
import numpy as np
def select_next_speaker(step: int, agents: List[DialogueAgent]) -> int:
bids = []
for agent in agents:
bid = ask_for_bid(agent)
bids.append(bid)
# randomly select among multiple agents with the same bid
max_value = np.max(bids)
max_indices = np.where(bids == max_value)[0]
idx = np.random.choice(max_indices)
print("Bids:")
for i, (bid, agent) in enumerate(zip(bids, agents)):
print(f"\t{agent.name} bid: {bid}")
if i == idx:
selected_name = agent.name
print(f"Selected: {selected_name}")
print("\n")
return idx
Main Loop
characters = []
for character_name, character_system_message, bidding_template in zip(
character_names, character_system_messages, character_bidding_templates
):
characters.append(
BiddingDialogueAgent(
name=character_name,
system_message=character_system_message,
model=ChatOpenAI(model='gpt-4o', temperature=0.2),
bidding_template=bidding_template,
)
)
max_iters = 10
n = 0
simulator = DialogueSimulator(agents=characters, selection_function=select_next_speaker)
simulator.reset()
simulator.inject("Debate Moderator", specified_topic)
print(f"(Debate Moderator): {specified_topic}")
print("\n")
while n < max_iters:
name, message = simulator.step()
print(f"({name}): {message}")
print("\n")
n += 1
(Debate Moderator): K-Pop의 글로벌 확장 과정에서 아티스트의 창의성을 유지하면서 동시에 높은 상업적 성공을 달성하는 최선의 방안은 무엇인가?
Bids:
방시혁 bid: 1
민희진 bid: 1
박진영 bid: 1
Selected: 민희진
(민희진): *눈을 반짝이며* 창의성은 K-Pop의 심장입니다. 아티스트들에게 더 많은 자율성을 주고, 다양한 문화와 협업을 통해 새로운 음악적 실험을 장려해야 합니다. 상업적 성공은 자연스럽게 따라올 것입니다.
Bids:
방시혁 bid: 3
민희진 bid: 1
박진영 bid: 3
Selected: 박진영
(박진영): *열정적으로 손을 흔들며* 창의성과 상업적 성공의 균형은 혁신적인 콘텐츠와 팬과의 진정성 있는 소통에서 나옵니다. 아티스트가 직접 팬들과 소통하고, 그들의 이야기를 음악에 담아내는 것이 중요합니다. 팬들은 진정성을 느낄 때 더 큰 지지를 보냅니다.
Bids:
방시혁 bid: 3
민희진 bid: 3
박진영 bid: 1
Selected: 방시혁
(방시혁): *미소를 지으며* K-Pop의 미래는 기술과 창의성의 융합에 달려 있습니다. AI와 VR을 활용해 팬들에게 몰입형 경험을 제공하고, 아티스트의 창의성을 극대화할 수 있는 플랫폼을 만들어야 합니다. 혁신이 곧 상업적 성공을 이끌 것입니다.
Bids:
방시혁 bid: 1
민희진 bid: 3
박진영 bid: 3
Selected: 박진영
(박진영): *열정적으로 손을 흔들며* K-Pop의 미래는 글로벌 팬덤과의 진정성 있는 연결에 달려 있습니다. 아티스트가 팬들과 직접 소통하고, 그들의 이야기를 음악과 퍼포먼스에 담아내는 것이 중요합니다. 진정성 있는 소통이 상업적 성공을 자연스럽게 이끌 것입니다.
Bids:
방시혁 bid: 3
민희진 bid: 3
박진영 bid: 1
Selected: 민희진
(민희진): *손을 가슴에 얹으며* K-Pop의 미래는 경계를 허무는 데 있습니다. 아티스트들이 다양한 장르와 예술 형식을 자유롭게 탐험할 수 있도록 지원해야 합니다. 팬들과의 소통은 물론, 예술적 도전을 통해 새로운 길을 개척하는 것이 중요합니다.
Bids:
방시혁 bid: 3
민희진 bid: 1
박진영 bid: 3
Selected: 방시혁
(방시혁): *자신감 있게 고개를 끄덕이며* K-Pop의 미래는 메타버스와 같은 디지털 혁신에 있습니다. 팬들이 가상 세계에서 아티스트와 상호작용하며, 새로운 형태의 공연과 콘텐츠를 경험할 수 있게 해야 합니다. 기술과 창의성의 결합이 무한한 가능성을 열어줄 것입니다.
Bids:
방시혁 bid: 1
민희진 bid: 3
박진영 bid: 3
Selected: 박진영
(박진영): *열정적으로 손을 흔들며* K-Pop의 미래는 팬들과의 진정성 있는 연결과 혁신적인 콘텐츠에 있습니다. 아티스트가 팬들과 직접 소통하고, 그들의 이야기를 음악과 퍼포먼스에 담아내는 것이 중요합니다. 진정성 있는 소통이 상업적 성공을 자연스럽게 이끌 것입니다.
Bids:
방시혁 bid: 3
민희진 bid: 3
박진영 bid: 1
Selected: 민희진
(민희진): *눈을 반짝이며* K-Pop의 미래는 예술과 기술의 경계를 넘는 데 있습니다. 아티스트들이 AI와 협업해 새로운 음악적 경지를 탐험하고, 팬들과의 소통을 통해 진정성을 유지하면서도 혁신적인 콘텐츠를 만들어야 합니다. 창의성은 무한한 가능성을 열어줍니다.
Bids:
방시혁 bid: 1
민희진 bid: 1
박진영 bid: 3
Selected: 박진영
(박진영): *열정적으로 손을 흔들며* K-Pop의 미래는 글로벌 팬덤과의 진정성 있는 연결에 달려 있습니다. 아티스트가 팬들과 직접 소통하고, 그들의 이야기를 음악과 퍼포먼스에 담아내는 것이 중요합니다. 진정성 있는 소통이 상업적 성공을 자연스럽게 이끌 것입니다.
Bids:
방시혁 bid: 3
민희진 bid: 3
박진영 bid: 1
Selected: 민희진
(민희진): *손을 펼치며* K-Pop의 미래는 아티스트의 자율성과 팬의 참여가 결합된 새로운 창작 환경에 있습니다. 팬들이 직접 콘텐츠 제작에 참여하고, 아티스트와 함께 성장하는 경험을 제공해야 합니다. 이로써 진정성과 혁신이 공존하는 K-Pop을 만들어갈 수 있습니다.
Last updated