Skip to content

Commit

Permalink
Merge pull request #51 from Cormanz/agents
Browse files Browse the repository at this point in the history
Implement SmartGPT API.
  • Loading branch information
Cormanz authored May 29, 2023
2 parents 2ee7f9d + 9273602 commit a73387f
Show file tree
Hide file tree
Showing 21 changed files with 335 additions and 212 deletions.
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
name = "smartgpt"
version = "0.1.0"
edition = "2021"
license = "MIT"
description = "A crate that provides LLMs with the ability to complete complex tasks using plugins."
homepage = "https://smartgpt.dev"
repository = "https://github.com/Cormanz/smartgpt"
documentation = "https://corman.gitbook.io/smartgpt/"
keywords = [ "llm", "agent", "autogpt" ]
readme = "README.md"

[dependencies]
async-openai = "0.10.2"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Currently, testing with SmartGPT is primarily being done with GPT3.5, and occasi

SmartGPT is an **incredibly experimental** application. The goal is to unlock maximum potential out of LLMs, and stability is sacrificed for this. Backwards compatibility is a fever dream here. However, SmartGPT is also housing some of the most innovative ideas and experiments in the AutoGPT space right now, and although most are unsuccessful, a few hit the dart-board and stick.

## Cargo Quickstart
## Quickstart

1. Install [`cargo`](https://doc.rust-lang.org/cargo/getting-started/installation.html), preferably the latest stable version.

Expand All @@ -49,7 +49,7 @@ SmartGPT is an **incredibly experimental** application. The goal is to unlock ma

4. Adjust the config to your liking, and execute it once again.

If you want more information, [read the documentation](https://corman.gitbook.io/smartgpt/installation).
If you want more information, or would like to use SmartGPT as a crate in your own projects, [read the documentation](https://corman.gitbook.io/smartgpt/installation).

# How SmartGPT Works

Expand Down
File renamed without changes.
27 changes: 7 additions & 20 deletions src/config/mod.rs → src/api/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use colored::Colorize;
use serde::{Serialize, Deserialize};
use serde_json::Value;

use crate::{CommandContext, LLM, Plugin, create_browse, create_google, create_filesystem, create_wolfram, create_news, LLMProvider, create_model_chatgpt, Agents, LLMModel, create_model_llama, AgentInfo, MemoryProvider, create_memory_local, create_memory_qdrant, MemorySystem, create_memory_redis, create_assets, PluginStore, create_brainstorm};
use crate::{CommandContext, LLM, Plugin, create_browse, create_google, create_filesystem, create_wolfram, create_news, LLMProvider, create_model_chatgpt, Agents, LLMModel, create_model_llama, AgentInfo, MemoryProvider, create_memory_local, create_memory_qdrant, MemorySystem, create_memory_redis, create_assets, PluginStore, create_brainstorm, SmartGPT};

mod default;
pub use default::*;
Expand Down Expand Up @@ -72,16 +72,7 @@ pub struct Llm {
pub enum AutoType {
#[serde(rename = "runner")] Runner {
task: String
},
#[serde(rename = "assistant")] Assistant {
#[serde(rename = "assistant token limit")] token_limit: Option<u16>
},
}

pub struct ProgramInfo {
pub personality: String,
pub auto_type: AutoType,
pub context: Arc<Mutex<CommandContext>>
}
}

pub fn list_plugins() -> Vec<Plugin> {
Expand Down Expand Up @@ -111,7 +102,7 @@ pub fn create_memory_providers() -> Vec<Box<dyn MemoryProvider>> {
]
}

pub fn create_llm_model(agent: HashMap<String, Value>) -> Result<Box<dyn LLMModel>, Box<dyn Error>> {
fn create_llm_model(agent: HashMap<String, Value>) -> Result<Box<dyn LLMModel>, Box<dyn Error>> {
let (model_name, model_config) = agent.iter().next().ok_or(NoLLMError)?;
let providers = create_llm_providers();
let llm_provider = providers.iter()
Expand All @@ -122,7 +113,7 @@ pub fn create_llm_model(agent: HashMap<String, Value>) -> Result<Box<dyn LLMMode
Ok(llm_provider.create(model_config.clone())?)
}

pub fn create_memory_model(agent: HashMap<String, Value>) -> Result<Box<dyn MemorySystem>, Box<dyn Error>> {
fn create_memory_model(agent: HashMap<String, Value>) -> Result<Box<dyn MemorySystem>, Box<dyn Error>> {
let (model_name, model_config) = agent.iter().next().ok_or(NoLLMError)?;
let providers = create_memory_providers();
let memory_provider = providers.iter()
Expand All @@ -146,7 +137,7 @@ pub fn create_agent(agent: AgentConfig) -> Result<AgentInfo, Box<dyn Error>> {
})
}

pub fn load_config(config: &str) -> Result<ProgramInfo, Box<dyn Error>> {
pub fn load_config(config: &str) -> Result<SmartGPT, Box<dyn Error>> {
let config: Config = serde_yaml::from_str(config)?;

let plugins = list_plugins();
Expand All @@ -163,11 +154,8 @@ pub fn load_config(config: &str) -> Result<ProgramInfo, Box<dyn Error>> {
}

let mut context = CommandContext {
auto_type: config.auto_type.clone(),
tool_out: vec![],
variables: HashMap::new(),
assets: HashMap::new(),
plugin_data: PluginStore(HashMap::new()),
plugin_data: PluginStore::new(),
plugins: vec![],
disabled_tools: config.disabled_tools,
agents: Agents {
Expand All @@ -189,9 +177,8 @@ pub fn load_config(config: &str) -> Result<ProgramInfo, Box<dyn Error>> {
}
}

Ok(ProgramInfo {
Ok(SmartGPT {
personality: config.personality,
auto_type: config.auto_type.clone(),
context: Arc::new(Mutex::new(context))
})
}
5 changes: 5 additions & 0 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod config;
mod smartgpt;

pub use config::*;
pub use smartgpt::*;
43 changes: 43 additions & 0 deletions src/api/smartgpt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use std::{sync::{Mutex, Arc}, collections::HashMap, error::Error, vec};

use serde::Serialize;
use serde_json::Value;

use crate::{CommandContext, PluginStore, Agents, AgentInfo, LLMProvider, LLMModel, LLM, ChatGPTProvider, ChatGPTConfig, memory_from_provider, LocalProvider, auto::{run_auto, Action, DisallowedAction, Update}};
pub struct SmartGPT {
pub personality: String,
pub context: Arc<Mutex<CommandContext>>
}

impl SmartGPT {
fn create() -> Result<(), Box<dyn Error>> {
let smartgpt = SmartGPT {
personality: "A superintelligent AI".to_string(),
context: Arc::new(Mutex::new(CommandContext {
agents: Agents::same(|| Ok(AgentInfo {
llm: LLM::from_provider(ChatGPTProvider, ChatGPTConfig {
api_key: "X".to_string(),
..Default::default()
})?,
observations: memory_from_provider(LocalProvider, Value::Null)?,
reflections: memory_from_provider(LocalProvider, Value::Null)?
}))?,
plugin_data: PluginStore::new(),
assets: HashMap::new(),
plugins: vec![],
disabled_tools: vec![]
}))
};

Ok(())
}

pub fn run_task(
&mut self,
task: &str,
allow_action: &impl Fn(&Action) -> Result<(), DisallowedAction>,
listen_to_update: &impl Fn(&Update) -> Result<(), Box<dyn Error>>
) -> Result<String, Box<dyn Error>> {
run_auto(self, task, allow_action, listen_to_update)
}
}
35 changes: 19 additions & 16 deletions src/auto/agents/worker/adept.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use std::{error::Error, ops::Deref, fmt::Display};
use colored::Colorize;
use serde::{Serialize, Deserialize};

use crate::{CommandContext, AgentInfo, Message, auto::{try_parse_json, agents::{worker::{log_yaml, run_method_agent}}}, ScriptValue};
use crate::{CommandContext, AgentInfo, Message, auto::{try_parse_json, agents::{worker::{log_yaml, run_method_agent}}, run::Action, DisallowedAction, DynamicUpdate}, ScriptValue};

use super::Update;

#[derive(Debug, Clone)]
pub struct NoDecisionTypeError(pub String);
Expand Down Expand Up @@ -62,7 +64,9 @@ pub fn get_response(
get_agent: &impl Fn(&mut CommandContext) -> &mut AgentInfo,
get_planner_agent: &impl Fn(&mut CommandContext) -> &mut AgentInfo,
thoughts: &BrainThoughts,
personality: &str
personality: &str,
allow_action: &impl Fn(&Action) -> Result<(), DisallowedAction>,
listen_to_update: &impl Fn(&Update) -> Result<(), Box<dyn Error>>
) -> Result<String, Box<dyn Error>> {
match thoughts.decision.decision_type.deref() {
"spawn_agent" => {
Expand All @@ -79,8 +83,7 @@ pub fn get_response(
);
}

let out = run_method_agent(context, get_agent, get_planner_agent, &instruction, &desire, data, personality)?;
println!("\n{out}\n");
let out = run_method_agent(context, get_agent, get_planner_agent, &instruction, &desire, data, personality, allow_action, listen_to_update)?;
Ok(out)
},
"brainstorm" => {
Expand All @@ -101,7 +104,9 @@ pub fn run_brain_agent(
context: &mut CommandContext,
get_agent: &impl Fn(&mut CommandContext) -> &mut AgentInfo,
task: &str,
personality: &str
personality: &str,
allow_action: &impl Fn(&Action) -> Result<(), DisallowedAction>,
listen_to_update: &impl Fn(&Update) -> Result<(), Box<dyn Error>>
) -> Result<String, Box<dyn Error>> {
let agent = get_agent(context);

Expand All @@ -122,13 +127,11 @@ Respond in this JSON format:
```
"#).trim().to_string()));

println!("{}\n", "Dynamic Agent".blue().bold());

let plan = try_parse_json::<DynamicPlan>(&agent.llm, 2, Some(1000), Some(0.3))?;
agent.llm.message_history.push(Message::Assistant(plan.raw));
let plan = plan.data;

log_yaml(&plan)?;
listen_to_update(&Update::DynamicAgent(DynamicUpdate::Plan(plan.plan.clone())))?;

agent.llm.message_history.push(Message::User(format!(r#"
Your goal is to complete the task by spawning agents to complete smaller subtasks.
Expand Down Expand Up @@ -164,21 +167,21 @@ Respond in this exact JSON format exactly, with every field in order:
}}
```"#, plan.plan)));

println!("{}\n", "Dynamic Agent".blue().bold());

let thoughts = try_parse_json::<BrainThoughts>(&agent.llm, 2, Some(1000), Some(0.3))?;
agent.llm.message_history.push(Message::Assistant(thoughts.raw));
let thoughts = thoughts.data;

log_yaml(&thoughts)?;
listen_to_update(&Update::DynamicAgent(DynamicUpdate::Thoughts(thoughts.clone())))?;

drop(agent);
let mut response = get_response(
context,
&|ctx| &mut ctx.agents.static_agent,
&|ctx| &mut ctx.agents.planner,
&thoughts,
&personality
&personality,
allow_action,
listen_to_update
)?;

if thoughts.decision.decision_type == "final_response" {
Expand Down Expand Up @@ -222,20 +225,20 @@ You may only provide these assets when spawning agents.
```
"#).trim().to_string()));

println!("{}\n", "Dynamic Agent".blue().bold());

let thoughts = try_parse_json::<BrainThoughts>(&agent.llm, 2, Some(1000), Some(0.5))?;
agent.llm.message_history.push(Message::Assistant(thoughts.raw));
let thoughts = thoughts.data;

log_yaml(&thoughts)?;
listen_to_update(&Update::DynamicAgent(DynamicUpdate::Thoughts(thoughts.clone())))?;

response = get_response(
context,
&|ctx| &mut ctx.agents.static_agent,
&|ctx| &mut ctx.agents.planner,
&thoughts,
&personality
&personality,
allow_action,
listen_to_update
)?;

if thoughts.decision.decision_type == "final_response" {
Expand Down
Loading

0 comments on commit a73387f

Please sign in to comment.