15个版本

0.2.3 2024年8月21日
0.2.2 2024年7月27日
0.2.1 2024年6月6日
0.0.8 2024年3月22日
0.0.0 2023年9月19日

#12 in 机器人

Download history 21/week @ 2024-05-03 102/week @ 2024-05-24 119/week @ 2024-05-31 56/week @ 2024-06-07 5/week @ 2024-06-14 7/week @ 2024-06-28 65/week @ 2024-07-05 218/week @ 2024-07-26 15/week @ 2024-08-02 119/week @ 2024-08-16

每月352次下载

自定义许可

190KB
5.5K SLoC

dimas

DiMAS - 构建分布式多智能体系统的框架

⚠️ 警告 ⚠️ : DiMAS正在积极开发中,因此文档和实现之间存在差距。

分布式多智能体系统是一组广泛分布但某种程度相连的独立智能体。它们被设计成可以通过协同工作来解决复杂任务。

该系统具有以下特点

  • 一个相对较大且复杂的环境
  • 包含一组(非智能体)对象,智能体可以感知、创建、移动、修改或销毁这些对象
  • 由于外部规则而随时间变化

有多个智能体在该环境中运行,它们

  • 可以在一定程度上感知环境
  • 可以与一些或所有其他智能体进行通信
  • 具有影响环境的一定能力

此crate可在crates.io上找到。

DiMAS遵循语义版本控制原则,增强之处在于,直到版本1.0.0,每个新次要版本都有破坏性更改,而补丁是非破坏性更改,但可能包括增强。

用法

DiMAS需要一个async运行时。您必须将您的main函数定义为async函数。

因此,在您的Cargo.toml的依赖项部分中包含dimas以及一个异步运行时。由于DiMAS使用tokio作为异步运行时,因此最好使用tokio来构建您的应用程序。请确保您使用了一个多线程运行时,否则DiMAS将会崩溃。

您的Cargo.toml应包括

[dependencies]
dimas = "0.2"
tokio = { version = "1", features = ["macros"] }

返回一个 Result 也是有道理的,因为一些函数可能会返回一个。DiMAS 错误始终是类型 Box<dyn std::error::Error>,并且应该是线程安全的。DiMAS 提供了一个类型定义 Result<T>,以便使生活更加简单

合适的主程序骨架可能看起来像

use dimas::prelude::*;

#[tokio::main]
async fn main() -> Result<()> {

    // your code
    // ...

    Ok(())
}

示例

一个非常简单的示例至少包括两个代理,一个 publisher 发布消息,一个 subscriber 监听这些消息。

此发布/订阅示例的 Cargo.toml 应包括

[dependencies]
dimas = version = "0.2"
tokio = { version = "1",features = ["macros"] }

发布者

publisher.rs 应看起来像这样

use dimas::prelude::*;
use std::time::Duration;

/// The Agent's properties
#[derive(Debug)]
struct AgentProps {
    counter: u128,
}

#[tokio::main]
async fn main() -> Result<()> {
    // create & initialize agents properties
    let properties = AgentProps { counter: 0 };

    // create an agent with the properties and default configuration
    let mut agent = Agent::new(properties)
       .config(&Config::default())?;

    // create publisher for topic "hello"
    agent
        .publisher()
        .topic("hello")
        .add()?;

    // use a timer for regular publishing of "hello" topic
    agent
        // get the TimerBuilder from the agent
        .timer()
        // set a name for the timer
        .name("timer")
        // every second
        .interval(Duration::from_secs(1))
        // the timers callback function as a closure
        .callback(
            |ctx| -> Result<()> {
                let counter = ctx
                    .read()?
                    .counter;
                // the message to send
                let text = format!("Hello World! [{counter}]");
                // just to see what will be sent
                println!("Sending '{}'", &text);
                // publishing with stored publisher for topic "hello"
                let message = Message::encode(&text);
                ctx.put("hello", message)?;
                // modify counter in properties
                ctx
                    .write()?
                    .counter += 1;
                Ok(())
            }
        )
        // finally add the timer to the agent
        // errors will be propagated to main
        .add()?;

    // start the agent
    agent.start().await?;
    Ok(())
}

订阅者

subscriber.rs 应看起来像这样

use dimas::prelude::*;

/// The Agent's properties
#[derive(Debug)]
pub struct AgentProps {}

fn callback(_ctx: &Context<AgentProps>, message: Message) -> Result<()> {
    let message: String = message.decode()?;
    println!("Received '{message}'");
    Ok(())
}

#[tokio::main]
async fn main() -> Result<()> {
    // create & initialize agents properties
    let properties = AgentProps {};

    // create an agent with the properties and default configuration
    let agent = Agent::new(properties)
        .config(&Config::default())?;

    // subscribe to "hello" messages
    agent
        // get the SubscriberBuilder from the agent
        .subscriber()
        //set wanted message topic (corresponding to publishers topic!)
        .topic("hello")
        // set the callback function for put messages
        .put_callback(callback)
        // finally add the subscriber to the agent
        // errors will be propagated to main
        .add()?;

    // start the agent
    agent.start().await?;
    Ok(())
}

更多示例

您可以在 dimas-fw/dimas/examples 中找到一些简单的示例,以及在 dimas-fw/examples 中找到更复杂的示例

依赖项

~28–41MB
~650K SLoC