示例展示了如何实现一个多代理模拟,其中一个特权代理决定谁来发言。
这遵循与多代理分散式发言人选择相反的选择方案。
我们在一个虚构的新闻网络模拟环境中展示这种方法的一个例子。这个例子将展示我们如何实现能够:
- 在说话前思考
- 终止对话
的代理。
导入LangChain相关模块
import functools
import random
from collections import OrderedDict
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
# 导入所需的Python模块和LangChain组件
# 包括功能性工具、随机数生成、有序字典、类型提示
# 以及LangChain的输出解析器、提示模板、消息模式和OpenAI聊天模型
DialogueAgent
和 DialogueSimulator
类
我们将使用在其他示例多人龙与地下城和分散式发言人选择中定义的相同 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:
"""
应用聊天模型到消息历史并返回消息字符串
"""
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:
"""
将{name}说的{message}连接到消息历史中
"""
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):
"""
用{name}的{message}启动对话
"""
for agent in self.agents:
agent.receive(name, message)
# 增加时间步
self._step += 1
def step(self) -> tuple[str, str]:
# 1. 选择下一个说话者
speaker_idx = self.select_next_speaker(self._step, self.agents)
speaker = self.agents[speaker_idx]
# 2. 下一个说话者发送消息
message = speaker.send()
# 3. 每个人接收消息
for receiver in self.agents:
receiver.receive(speaker.name, message)
# 4. 增加时间步
self._step