构建LangChain应用程序的示例代码:56、如何实现一个多智能体模拟,其中没有固定的发言顺序。智能体自行决定谁来发言,通过竞价机制实现

多智能体分散式发言人选择

示例展示了如何实现一个多智能体模拟,其中没有固定的发言顺序。智能体自行决定谁来发言,通过竞价机制实现。

我们将在下面的示例中展示一场虚构的总统辩论来演示这一过程。

导入LangChain相关模块

from typing import Callable, Listimport tenacity
from langchain.output_parsers import RegexParser
from langchain.prompts import PromptTemplate
from langchain.schema import (HumanMessage,SystemMessage,
)
from langchain_openai import ChatOpenAI# 导入所需的模块和类
# typing: 用于类型注解
# tenacity: 用于实现重试机制
# langchain相关模块: 用于构建对话系统

DialogueAgentDialogueSimulator

我们将使用在 Multi-Player Dungeons & Dragons 中定义的相同 DialogueAgentDialogueSimulator 类。

class DialogueAgent:def __init__(self,name: str,system_message: SystemMessage,model: ChatOpenAI,) -> None:self.name = nameself.system_message = system_messageself.model = modelself.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.contentdef 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 = agentsself._step = 0self.select_next_speaker = selection_functiondef 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 += 1def 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 += 1return speaker.name, message# DialogueAgent类: 表示对话中的一个智能体
# DialogueSimulator类: 用于模拟多个智能体之间的对话

BiddingDialogueAgent

我们定义了 DialogueAgent 的一个子类,它有一个 bid() 方法,根据消息历史和最近的消息产生一个出价。

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_templatedef bid(self) -> str:"""要求聊天模型输出一个发言出价"""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)]).contentreturn bid_string# BiddingDialogueAgent类: DialogueAgent的子类,增加了竞价功能

定义参与者和辩论主题

character_names = ["Donald Trump", "Kanye West", "Elizabeth Warren"]
topic = "transcontinental high speed rail"
word_limit = 50# 定义参与辩论的人物和辩论主题
# character_names: 参与者姓名列表
# topic: 辩论主题
# word_limit: 回答字数限制

生成系统消息

game_description = f"""Here is the topic for the presidential debate: {topic}.
The presidential candidates are: {', '.join(character_names)}."""player_descriptor_system_message = SystemMessage(content="You can add detail to the description of each presidential candidate."
)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 presidential candidate, {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).contentreturn character_descriptiondef generate_character_header(character_name, character_description):return f"""{game_description}
Your name is {character_name}.
You are a presidential candidate.
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 candidate.
"""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)
]# 生成系统消息和角色描述
# generate_character_description: 生成角色描述
# generate_character_header: 生成角色头部信息
# generate_character_system_message: 生成角色系统消息
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}")# 打印生成的角色描述、头部信息和系统消息

出价的输出解析器

我们要求智能体输出一个发言出价。但由于智能体是输出字符串的LLM,我们需要:

  1. 定义他们将产生输出的格式
  2. 解析他们的输出

我们可以继承 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"
)# BidOutputParser类: 自定义的出价输出解析器
# bid_parser: 实例化的出价解析器

生成竞价系统消息

这受到 Generative Agents 中使用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_templatecharacter_bidding_templates = [generate_character_bidding_template(character_header)for character_header in character_headers
]# generate_character_bidding_template: 生成角色竞价模板
# character_bidding_templates: 所有角色的竞价模板列表
for character_name, bidding_template in zip(character_names, character_bidding_templates
):print(f"{character_name} Bidding Template:")print(bidding_template)# 打印生成的竞价模板

使用LLM详细阐述辩论主题

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 presidential candidates: {*character_names,}.Do not add anything else."""),
]
specified_topic = ChatOpenAI(temperature=1.0)(topic_specifier_prompt).contentprint(f"Original topic:\n{topic}\n")
print(f"Detailed topic:\n{specified_topic}\n")# 使用LLM生成更详细的辩论主题

定义发言人选择函数

最后,我们将定义一个发言人选择函数 select_next_speaker,它接受每个智能体的出价并选择出价最高的智能体(同分随机打破平局)。

我们将定义一个 ask_for_bid 函数,使用我们之前定义的 bid_parser 来解析智能体的出价。我们将使用 tenacity 来装饰 ask_for_bid,在智能体的出价无法正确解析时多次重试,并在达到最大尝试次数后生成默认出价0。

@tenacity.retry(stop=tenacity.stop_after_attempt(2),wait=tenacity.wait_none(),  # 重试之间没有等待时间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,
)  # 当所有重试都用尽时的默认值
def ask_for_bid(agent) -> str:"""请求智能体出价并将出价解析为正确的格式。"""bid_string = agent.bid()bid = int(bid_parser.parse(bid_string)["bid"])return bid# ask_for_bid: 请求智能体出价并解析
# 使用tenacity装饰器处理可能的错误和重试
import numpy as npdef select_next_speaker(step: int, agents: List[DialogueAgent]) -> int:bids = []for agent in agents:bid = ask_for_bid(agent)bids.append(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.nameprint(f"Selected: {selected_name}")print("\n")return idx# select_next_speaker: 选择下一个发言者
# 根据智能体的出价选择出价最高的智能体

主循环

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(temperature=0.2),bidding_template=bidding_template,))# 创建BiddingDialogueAgent实例列表
max_iters = 10
n = 0simulator = 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# 主循环
# max_iters: 最大对话轮数
# simulator: 对话模拟器实例
# 循环执行对话步骤,每步选择一个发言者并打印其消息

扩展知识:

  1. 多智能体系统:这个例子展示了一个复杂的多智能体系统,其中多个AI智能体互相交互。这种系统可以用于模拟各种复杂的社会互动场景,如辩论、谈判或团队协作。

  2. 竞价机制:使用竞价机制来决定发言顺序是一种创新的方法。这模拟了真实辩论中参与者争夺发言机会的动态过程。

  3. 角色扮演:每个AI智能体都被赋予了特定的角色和个性。这种方法可以用于创建更加真实和多样化的对话场景。

  4. 错误处理:使用tenacity库进行错误处理和重试是一个很好的实践,特别是在处理可能不稳定的AI模型输出时。

  5. 提示工程:代码中展示了如何通过精心设计的提示来引导AI模型生成特定格式的输出,这是LLM应用中的一个关键技能。

  6. 输出解析:使用正则表达式解析器来处理AI模型的输出,确保获取所需的信息格式。

  7. 模块化设计:代码通过定义不同的类和函数,实现了良好的模块化设计,使得系统易于理解和扩展。

这个例子展示了如何将多个LangChain和OpenAI的功能结合起来,创建一个复杂的AI驱动的对话系统。它不仅模拟了一个有趣的总统辩论场景,还展示了如何处理多智能体交互、角色扮演、动态发言顺序等复杂问题。这种方法可以扩展到各种需要模拟复杂人际互动的应用场景中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/41304.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

正向代理反向代理

nginx的正向代理和反向代理: 正向代理以及缓存配置: 代理:客户端不再是直接访问服务端&#xff0c;通过代理服务器访问服务端。 正向代理&#xff1a;面向客户端&#xff0c;通过代理服务器的ip地址访问目标服务端 服务端只知道代理服务器的地址&#xff0c;真正的客户端ip可以…

【MySQL系列】隐式转换

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

ctfshow web入门 nodejs

web334 有个文件下载之后改后缀为zip加压就可以得到两个文件 一个文件类似于index.php 还有一个就是登录密码登录成功就有flag username:ctfshow password:123456因为 return name!CTFSHOW && item.username name.toUpperCase() && item.password passwor…

产科管理系统 专科电子病历系统源码,前后端分离架构,多家医院产科广泛运用,系统稳定,功能齐全

产科管理系统 专科电子病历系统源码&#xff0c;前后端分离架构&#xff0c;多家医院产科广泛运用&#xff0c;系统稳定&#xff0c;功能齐全 产科管理系统&#xff0c;特别是产科信息管理系统&#xff08;Obstetrical Information Management System&#xff0c;简称OIMS&…

智能井盖监测系统:守护城市安全的新防线

​ ​​在快速发展的现代都市中&#xff0c;井盖作为连接地上与地下世界的“隐形门”&#xff0c;其安全状态直接关系到市民的生命财产安全。随着物联网、大数据及人工智能技术的飞速发展&#xff0c;智能井盖监测系统的出现为解决传统井盖管理难题提供了创新方案&#xff0…

【算法笔记自学】入门篇(2)——算法初步

4.1排序 自己写的题解 #include <stdio.h> #include <stdlib.h>void selectSort(int A[], int n) {for(int i 0; i < n - 1; i) { // 修正索引范围int k i;for(int j i 1; j < n; j) { // 修正索引范围if(A[j] < A[k]) {k j;}}if (k ! i) { // 仅在…

跨境人最怕的封店要怎么规避?

跨境人最怕的是什么&#xff1f;——封店 造成封店的原因很多&#xff0c;IP关联、无版权售卖、虚假发货等等&#xff0c;其中IP关联这个问题导致店铺被封在跨境商家中简直是屡见不鲜 IP关联&#xff0c;是指被海外平台检测到多家店铺开设在同一个站点上的情况。我们知道有些…

卖家必读:阿里巴巴国际站登录与入驻全流程

阿里巴巴国际站作为全球最大的B2B电子商务平台之一&#xff0c;为品牌建立和业务拓展提供了可能。那么跨境卖家如何才能成功登录和入驻阿里巴巴国际站&#xff1f;本文将讲解如何用阿里巴巴国际站网页版进行登录&#xff0c;以及阿里巴巴国际站卖家的入驻条件、流程和费用。此外…

统计信号处理基础 习题解答11-12

题目 证明 的MAP估计量为 其中是一个的矢量, 是一个可逆的p*p的矩阵。也就是说&#xff0c;MAP估计量对可逆的线性变换是可以变换的。 解答 已知的联合概率密度 且&#xff1a; 现在知道&#xff1a; 那么为了获得变换后的MAP&#xff0c;首先需要根据求出 根据概率密度变换…

2024年软件测试面试题,精选100+,附答案+文档

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Part1 1、你的测试职业发展是什么&#xff1f; 测试经验越多&#xff0c;测试能力越高。所以我…

C++入门 容器适配器 / stack queue模拟实现

目录 容器适配器 deque的原理介绍 stack模拟实现 queue模拟实现 priority_queue模拟实现 仿函数 容器适配器 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总 结)&#xff0c;该种模式是将一个类的接口转换成客户希望…

深度学习Week19——学习残差网络和ResNet50V2算法

文章目录 深度学习Week18——学习残差网络和ResNet50V2算法 一、前言 二、我的环境 三、论文解读 3.1 预激活设计 3.2 残差单元结构 四、模型复现 4.1 Residual Block 4.2 堆叠Residual Block 4.3. ResNet50V2架构复现 一、前言 &#x1f368; 本文为&#x1f517;365天深度学…

Kubernetes k8s 命名空间 namespace 介绍以及应用 资源限额配置

目录 命名空间 什么是命名空间&#xff1f; namespace应用场景 namespacs使用案例分享 namespace资源限额 文档中的YAML文件配置直接复制粘贴可能存在格式错误&#xff0c;故实验中所需要的YAML文件以及本地包均打包至网盘 链接&#xff1a;https://pan.baidu.com/s/1qv8Tc…

Python中异步事件触发

1、问题背景 在Python中&#xff0c;我想创建一个由事件生成控制流程的类结构。为此&#xff0c;我做了以下工作&#xff1a; class MyEvent: EventName_FunctionName {}classmethoddef setup(cls, notificationname, functionname):if notificationname in MyEvent.EventN…

ONLYOFFICE 8.1版本震撼来袭,让办公更高效、更智能

官网链接&#xff1a; 在线PDF查看器和转换器 | ONLYOFFICE 在线办公套件 | ONLYOFFICE 随着科技的不断发展&#xff0c;办公软件已经成为现代企业提高工作效率、实现信息共享的重要工具。在我国&#xff0c;一款名为ONLYOFFICE的在线办公套件受到了越来越多企业的青睐。今天…

golang中的类型转换那些事

由于golang是一门强类型的语言&#xff0c; 所以我们在golang的开发中不可避免的会对一些数据类型进行手动转换&#xff0c;以适应我们的业务需求。 golang中类型转换的途径大致有4种&#xff0c;强制转换&#xff0c;类型断言&#xff0c;类型匹配 还有使用strconv包中提供的…

[TensorFlow-Lite][深度学习]【快速简介-1】

前言&#xff1a; 很多场景下面我们需要需要把我们的深度学习模型部署到Android,IOS 手机上面. Google 通过TensorFlow Lite 提供了对应的解决方案. 目录&#xff1a; 端侧部署优点 硬件支持 性能 应用案例 一 端侧部署优点 1; 很多场景下面&#xff1a; 无网络,数据无法…

Hadoop 远程 debug

Hadoop 命令行 在执行 hadoop fs 命令行之前&#xff0c;先执行以下命令&#xff1a; export HADOOP_CLIENT_OPTS"-Xdebug -Xrunjdwp:transportdt_socket,servery,suspendy,address8000"

昇思25天学习打卡营第10天|基于MindSpore实现BERT对话情绪识别

基于MindSpore实现BERT对话情绪识别 模型简介数据集模型构建模型验证模型推理自定义推理数据集 模型简介 BERT全称是来自变换器的双向编码器表征量&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;&#xff0c;它是Google于2018年末开发并发…

HTML超链接和锚链接

HTML超链接和锚链接 一、定义 HTML的超链接&#xff08;Hyperlink&#xff09;用于在网页之间创建链接&#xff0c;使用户可以点击这些链接来导航到其他页面或资源。 二、基本语法 1、语法 HTML中的超链接使用a标签来定义 <a href"URL">链接文本</a&g…