Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '0.2' into feat/zep-notebook
Browse files Browse the repository at this point in the history
jackgerrits authored Oct 14, 2024
2 parents d7ad5c8 + 2834530 commit 208063a
Showing 10 changed files with 2,031 additions and 63 deletions.
9 changes: 0 additions & 9 deletions .github/workflows/deploy-website.yml
Original file line number Diff line number Diff line change
@@ -3,23 +3,14 @@ name: docs
on:
pull_request:
branches: ["0.2"]
paths:
- "autogen/*"
- "website/*"
- ".github/workflows/deploy-website.yml"
push:
branches: ["0.2"]
paths:
- "autogen/*"
- "website/*"
- ".github/workflows/deploy-website.yml"
workflow_dispatch:
permissions:
id-token: write
pages: write
jobs:
checks:
if: github.event_name != 'push'
runs-on: ubuntu-latest
defaults:
run:
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@

<div align="center">

<img src="https://microsoft.github.io/autogen/img/ag.svg" alt="AutoGen Logo" width="100">
<img src="https://microsoft.github.io/autogen/0.2/img/ag.svg" alt="AutoGen Logo" width="100">

![Python Version](https://img.shields.io/badge/3.8%20%7C%203.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue) [![PyPI - Version](https://img.shields.io/pypi/v/autogen-agentchat)](https://pypi.org/project/autogen-agentchat/)
[![NuGet version](https://badge.fury.io/nu/AutoGen.Core.svg)](https://badge.fury.io/nu/AutoGen.Core)
79 changes: 77 additions & 2 deletions autogen/agentchat/contrib/agent_builder.py
Original file line number Diff line number Diff line change
@@ -172,6 +172,26 @@ class AgentBuilder:
```
"""

AGENT_FUNCTION_MAP_PROMPT = """Consider the following function.
Function Name: {function_name}
Function Description: {function_description}
The agent details are given in the format: {format_agent_details}
Which one of the following agents should be able to execute this function, preferably an agent with programming background?
{agent_details}
Hint:
# Only respond with the name of the agent that is most suited to execute the function and nothing else.
"""

UPDATED_AGENT_SYSTEM_MESSAGE = """
{agent_system_message}
You have access to execute the function: {function_name}.
With following description: {function_description}
"""

def __init__(
self,
config_file_or_env: Optional[str] = "OAI_CONFIG_LIST",
@@ -358,6 +378,7 @@ def build(
self,
building_task: str,
default_llm_config: Dict,
list_of_functions: Optional[List[Dict]] = None,
coding: Optional[bool] = None,
code_execution_config: Optional[Dict] = None,
use_oai_assistant: Optional[bool] = False,
@@ -373,6 +394,7 @@ def build(
coding: use to identify if the user proxy (a code interpreter) should be added.
code_execution_config: specific configs for user proxy (e.g., last_n_messages, work_dir, ...).
default_llm_config: specific configs for LLM (e.g., config_list, seed, temperature, ...).
list_of_functions: list of functions to be associated with Agents
use_oai_assistant: use OpenAI assistant api instead of self-constructed agent.
user_proxy: user proxy's class that can be used to replace the default user proxy.
@@ -480,8 +502,9 @@ def build(
"code_execution_config": code_execution_config,
}
)

_config_check(self.cached_configs)
return self._build_agents(use_oai_assistant, user_proxy=user_proxy, **kwargs)
return self._build_agents(use_oai_assistant, list_of_functions, user_proxy=user_proxy, **kwargs)

def build_from_library(
self,
@@ -653,13 +676,18 @@ def build_from_library(
return self._build_agents(use_oai_assistant, user_proxy=user_proxy, **kwargs)

def _build_agents(
self, use_oai_assistant: Optional[bool] = False, user_proxy: Optional[autogen.ConversableAgent] = None, **kwargs
self,
use_oai_assistant: Optional[bool] = False,
list_of_functions: Optional[List[Dict]] = None,
user_proxy: Optional[autogen.ConversableAgent] = None,
**kwargs,
) -> Tuple[List[autogen.ConversableAgent], Dict]:
"""
Build agents with generated configs.
Args:
use_oai_assistant: use OpenAI assistant api instead of self-constructed agent.
list_of_functions: list of functions to be associated to Agents
user_proxy: user proxy's class that can be used to replace the default user proxy.
Returns:
@@ -695,6 +723,53 @@ def _build_agents(
)
agent_list = agent_list + [user_proxy]

agent_details = []

for agent in agent_list[:-1]:
agent_details.append({"name": agent.name, "description": agent.description})

if list_of_functions:
for func in list_of_functions:
resp = (
self.builder_model.create(
messages=[
{
"role": "user",
"content": self.AGENT_FUNCTION_MAP_PROMPT.format(
function_name=func["name"],
function_description=func["description"],
format_agent_details='[{"name": "agent_name", "description": "agent description"}, ...]',
agent_details=str(json.dumps(agent_details)),
),
}
]
)
.choices[0]
.message.content
)

autogen.agentchat.register_function(
func["function"],
caller=self.agent_procs_assign[resp][0],
executor=agent_list[0],
name=func["name"],
description=func["description"],
)

agents_current_system_message = [
agent["system_message"] for agent in agent_configs if agent["name"] == resp
][0]

self.agent_procs_assign[resp][0].update_system_message(
self.UPDATED_AGENT_SYSTEM_MESSAGE.format(
agent_system_message=agents_current_system_message,
function_name=func["name"],
function_description=func["description"],
)
)

print(f"Function {func['name']} is registered to agent {resp}.")

return agent_list, self.cached_configs.copy()

def save(self, filepath: Optional[str] = None) -> str:
866 changes: 866 additions & 0 deletions notebook/agentchat_huggingface_langchain.ipynb

Large diffs are not rendered by default.

426 changes: 426 additions & 0 deletions notebook/agentchat_webcrawling_with_spider.ipynb

Large diffs are not rendered by default.

470 changes: 470 additions & 0 deletions notebook/autobuild_function_calling.ipynb

Large diffs are not rendered by default.

141 changes: 124 additions & 17 deletions test/agentchat/contrib/test_agent_builder.py
Original file line number Diff line number Diff line change
@@ -3,15 +3,18 @@
import json
import os
import sys
from unittest.mock import MagicMock, patch

import pytest

import autogen
from autogen.agentchat.contrib.agent_builder import AgentBuilder

sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
sys.path.append(os.path.join(os.path.dirname(__file__), "../.."))

from conftest import reason, skip_openai # noqa: E402
from test_assistant_agent import KEY_LOC, OAI_CONFIG_LIST # noqa: E402
from test_assistant_agent import KEY_LOC, OAI_CONFIG_LIST # noqa: E402 # noqa: E402

try:
import chromadb
@@ -22,6 +25,7 @@
skip = False

here = os.path.abspath(os.path.dirname(__file__))
llm_config = {"temperature": 0}


def _config_check(config):
@@ -37,10 +41,27 @@ def _config_check(config):
assert agent_config.get("system_message", None) is not None


@pytest.mark.skipif(
skip_openai,
reason=reason,
)
# Function initializes a group chat with agents and starts a execution_task.
def start_task(execution_task: str, agent_list: list):
group_chat = autogen.GroupChat(agents=agent_list, messages=[], max_round=12)
manager = autogen.GroupChatManager(
groupchat=group_chat,
llm_config={"config_list": autogen.config_list_from_json(f"{KEY_LOC}/{OAI_CONFIG_LIST}"), **llm_config},
)

agent_list[0].initiate_chat(manager, message=execution_task)


ask_ossinsight_mock = MagicMock()


# Function to test function calling
def ask_ossinsight(question: str) -> str:
ask_ossinsight_mock(question)
return "The repository microsoft/autogen has 123,456 stars on GitHub."


@pytest.mark.skipif(skip_openai, reason=reason)
def test_build():
builder = AgentBuilder(
config_file_or_env=OAI_CONFIG_LIST,
@@ -69,6 +90,99 @@ def test_build():
assert len(agent_config["agent_configs"]) <= builder.max_agents


@pytest.mark.skipif(skip_openai or skip, reason=reason + "OR dependency not installed")
def test_build_assistant_with_function_calling():
list_of_functions = [
{
"name": "ossinsight_data_api",
"description": "This is an API endpoint allowing users (analysts) to input question about GitHub in text format to retrieve the related and structured data.",
"function": ask_ossinsight,
}
]

builder = AgentBuilder(
config_file_or_env=OAI_CONFIG_LIST, config_file_location=KEY_LOC, builder_model="gpt-4", agent_model="gpt-4"
)
building_task = "How many stars microsoft/autogen has on GitHub?"

agent_list, agent_config = builder.build(
building_task=building_task,
default_llm_config={"temperature": 0},
code_execution_config={
"last_n_messages": 2,
"work_dir": f"{here}/test_agent_scripts",
"timeout": 60,
"use_docker": "python:3",
},
list_of_functions=list_of_functions,
)

_config_check(agent_config)

# check number of agents
assert len(agent_config["agent_configs"]) <= builder.max_agents

# Mock the 'ask_ossinsight' function in the '_main_' module using a context manager.
with patch(f"{__name__}.ask_ossinsight") as mocked_function:
# Execute 'start_task' which should trigger 'ask_ossinsight' due to the given execution task.
start_task(
execution_task="How many stars microsoft/autogen has on GitHub?",
agent_list=agent_list,
)

# Verify that 'ask_ossinsight' was called exactly once during the task execution.
mocked_function.assert_called()


@pytest.mark.skipif(
skip_openai,
reason="requested to skip",
)
def test_build_gpt_assistant_with_function_calling():
list_of_functions = [
{
"name": "ossinsight_data_api",
"description": "This is an API endpoint allowing users (analysts) to input question about GitHub in text format to retrieve the related and structured data.",
"function": ask_ossinsight,
}
]

builder = AgentBuilder(
config_file_or_env=OAI_CONFIG_LIST, config_file_location=KEY_LOC, builder_model="gpt-4", agent_model="gpt-4"
)

building_task = "Determine number of stars of GitHub repositories"

agent_list, agent_config = builder.build(
building_task=building_task,
default_llm_config={"temperature": 0},
code_execution_config={
"last_n_messages": 2,
"work_dir": f"{here}/test_agent_scripts",
"timeout": 60,
"use_docker": "python:3",
},
list_of_functions=list_of_functions,
use_oai_assistant=True,
)

_config_check(agent_config)

# check number of agents
assert len(agent_config["agent_configs"]) <= builder.max_agents

# Mock the 'ask_ossinsight' function in the '_main_' module using a context manager.
with patch(f"{__name__}.ask_ossinsight") as mocked_function:
# Execute 'start_task' which should trigger 'ask_ossinsight' due to the given execution task.
start_task(
execution_task="How many stars microsoft/autogen has on GitHub?",
agent_list=agent_list,
)

# Verify that 'ask_ossinsight' was called exactly once during the task execution.
mocked_function.assert_called()


@pytest.mark.skipif(
skip_openai or skip,
reason=reason + "OR dependency not installed",
@@ -122,10 +236,7 @@ def test_build_from_library():
assert len(agent_config["agent_configs"]) <= builder.max_agents


@pytest.mark.skipif(
skip_openai,
reason=reason,
)
@pytest.mark.skipif(skip_openai, reason=reason)
def test_save():
builder = AgentBuilder(
config_file_or_env=OAI_CONFIG_LIST,
@@ -159,10 +270,7 @@ def test_save():
_config_check(saved_configs)


@pytest.mark.skipif(
skip_openai,
reason=reason,
)
@pytest.mark.skipif(skip_openai, reason=reason)
def test_load():
builder = AgentBuilder(
config_file_or_env=OAI_CONFIG_LIST,
@@ -188,10 +296,7 @@ def test_load():
_config_check(loaded_agent_configs)


@pytest.mark.skipif(
skip_openai,
reason=reason,
)
@pytest.mark.skipif(skip_openai, reason=reason)
def test_clear_agent():
builder = AgentBuilder(
config_file_or_env=OAI_CONFIG_LIST,
@@ -218,6 +323,8 @@ def test_clear_agent():

if __name__ == "__main__":
test_build()
test_build_assistant_with_function_calling()
test_build_gpt_assistant_with_function_calling()
test_build_from_library()
test_save()
test_load()
1 change: 1 addition & 0 deletions website/docs/Examples.md
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@ Links to notebook examples:
- Browse the Web with Agents - [View Notebook](https://github.com/microsoft/autogen/blob/0.2/notebook/agentchat_surfer.ipynb)
- **SQL**: Natural Language Text to SQL Query using the [Spider](https://yale-lily.github.io/spider) Text-to-SQL Benchmark - [View Notebook](https://github.com/microsoft/autogen/blob/0.2/notebook/agentchat_sql_spider.ipynb)
- **Web Scraping**: Web Scraping with Apify - [View Notebook](/docs/notebooks/agentchat_webscraping_with_apify)
- **Web Crawling**: Crawl entire domain with Spider API - [View Notebook](/docs/notebooks/agentchat_webcrawling_with_spider)
- **Write a software app, task by task, with specially designed functions.** - [View Notebook](https://github.com/microsoft/autogen/blob/0.2/notebook/agentchat_function_call_code_writing.ipynb).

### Human Involvement
86 changes: 52 additions & 34 deletions website/src/pages/index.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,58 @@
import React from 'react';
import clsx from 'clsx';
import Layout from '@theme/Layout';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import styles from './index.module.css';
import HomepageFeatures from '../components/HomepageFeatures';
import React from "react";
import clsx from "clsx";
import Layout from "@theme/Layout";
import Link from "@docusaurus/Link";
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import styles from "./index.module.css";
import HomepageFeatures from "../components/HomepageFeatures";

function HomepageHeader() {
const {siteConfig} = useDocusaurusContext();
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<h1 className="hero__title">{siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="/docs/Getting-Started">
Getting Started - 3min ⏱️
</Link>
</div>
</div>
</header>
);
const { siteConfig } = useDocusaurusContext();
return (
<header className={clsx("hero hero--primary", styles.heroBanner)}>
<div className="container">
<h1 className="hero__title">{siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<div className={styles.buttonWrapper}>
<Link
className="button button--secondary button--lg"
to="/docs/Getting-Started"
>
Get Started
</Link>
<p className={styles.buttonTagline}>
Current stable version of AutoGen (autogen-agentchat~=0.2)
</p>
</div>
<div className={styles.buttonWrapper}>
<Link
className="button button--secondary button--lg"
to="https://microsoft.github.io/autogen/dev/"
>
Preview v0.4
</Link>
<p className={styles.buttonTagline}>
A new event driven architecture for AutoGen
</p>
</div>
</div>
</div>
</header>
);
}

export default function Home() {
const {siteConfig} = useDocusaurusContext();
return (
<Layout
title={`AutoGen`}
description="Enabling Next-Gen LLM Applications via Multi-Agent Conversation Framework">
<HomepageHeader />
<main>
<HomepageFeatures />
</main>
</Layout>
);
const { siteConfig } = useDocusaurusContext();
return (
<Layout
title={`AutoGen`}
description="Enabling Next-Gen LLM Applications via Multi-Agent Conversation Framework"
>
<HomepageHeader />
<main>
<HomepageFeatures />
</main>
</Layout>
);
}
14 changes: 14 additions & 0 deletions website/src/pages/index.module.css
Original file line number Diff line number Diff line change
@@ -22,4 +22,18 @@
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}

.buttonWrapper {
display: flex;
flex-direction: column;
align-items: center;
}

.buttonTagline {
font-size: 0.8rem;
margin-top: 5px;
text-align: center;
max-width: 200px;
}

0 comments on commit 208063a

Please sign in to comment.