Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sample Web Application Built with AutoGen #695

Merged
merged 104 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from 95 commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
360e7b1
Adding research assistant code
pcdeadeasy Oct 20, 2023
74d9756
Adding research assistant code
pcdeadeasy Oct 20, 2023
1d40495
checking in RA files
pcdeadeasy Oct 20, 2023
ae66b9f
Remove used text file
pcdeadeasy Oct 20, 2023
1f13498
Merge pull request #1 from pcdeadeasy/ra-oss
pcdeadeasy Oct 20, 2023
c363ae9
Merge branch 'microsoft:main' into main
victordibia Oct 25, 2023
d9399ed
Update README.md to include Saleema's name to the Contributors list.
pcdeadeasy Oct 25, 2023
4e25ba5
remove extraneous files
victordibia Oct 25, 2023
5dab76f
update gitignore
victordibia Oct 25, 2023
a539f51
improve structure on global skills
victordibia Oct 25, 2023
6b15f0c
fix linting error
victordibia Oct 25, 2023
6fa1c9d
readme update
victordibia Oct 25, 2023
34bd93e
Merge branch 'main' of github.com:pcdeadeasy/autogen-oss into main
victordibia Oct 25, 2023
446cc0b
readme update
victordibia Oct 26, 2023
d034f50
fix wrong function bug
victordibia Oct 26, 2023
17c9045
readme update
victordibia Oct 26, 2023
62c2b77
update ui build
victordibia Oct 26, 2023
c5463b9
cleanup, remove unused modules
victordibia Oct 26, 2023
6dda83b
readme and docs updates
victordibia Oct 26, 2023
3a57159
set default user
victordibia Oct 26, 2023
89be92f
ui build update
victordibia Oct 26, 2023
6845c07
add screenshot to improve instructions
victordibia Oct 26, 2023
e53a5fb
remove logout behaviour, replace with note to developers to add their…
victordibia Oct 26, 2023
2253aae
Create blog and edit ARA README
pcdeadeasy Oct 28, 2023
fd00fdc
Added the stock prices example in the readme for ARA
pcdeadeasy Oct 28, 2023
bc0ae49
Include edits from review with Saleema
pcdeadeasy Oct 28, 2023
6aa0d28
fix format issues
pcdeadeasy Oct 28, 2023
671399e
Cosmetic changes for betting debug messages
pcdeadeasy Oct 28, 2023
0d9fc8a
edit authors
pcdeadeasy Oct 28, 2023
5430da7
remove references to request_timeout to support autogen v0.0.2
victordibia Oct 30, 2023
736f362
Merge branch 'main' of github.com:pcdeadeasy/autogen-oss into main
victordibia Oct 30, 2023
83b0610
Merge branch 'microsoft:main' into main
victordibia Oct 30, 2023
9fc1558
update bg color for UI
victordibia Oct 31, 2023
fac4850
readme update
victordibia Oct 31, 2023
e054981
Merge branch 'main' of github.com:pcdeadeasy/autogen-oss into main
victordibia Oct 31, 2023
9e4a83f
update research assistant blog post
victordibia Oct 31, 2023
f4e8f87
Merge branch 'microsoft:main' into main
victordibia Oct 31, 2023
1a142ce
omit samples folder from codecov
victordibia Oct 31, 2023
7dd6ab7
Merge branch 'main' of github.com:pcdeadeasy/autogen-oss into main
victordibia Oct 31, 2023
bd1f818
ui build update + precommit refactor
victordibia Oct 31, 2023
aba5503
formattiing updates fromo pre-commit
victordibia Oct 31, 2023
46f8615
readme update
victordibia Nov 1, 2023
f2e865a
remove compiled source files
victordibia Nov 1, 2023
84ec393
update gitignore
victordibia Nov 9, 2023
22ac3bf
refactor, file removals
victordibia Nov 9, 2023
5b2af4d
refactor for improved structure - datamodel, chat and db helper
victordibia Nov 9, 2023
3c5a172
Merge branch 'main' of github.com:pcdeadeasy/autogen-oss into main
victordibia Nov 9, 2023
782b86b
update gitignore
victordibia Nov 9, 2023
2990c69
refactor, file removals
victordibia Nov 9, 2023
7fd4df3
refactor for improved structure - datamodel, chat and db helper
victordibia Nov 9, 2023
14551e6
Merge branch 'react-app' of github.com:pcdeadeasy/autogen-oss into re…
victordibia Nov 9, 2023
fac37e5
refactor skills view
victordibia Nov 9, 2023
b8bbb43
general refactor
victordibia Nov 9, 2023
affe887
gitignore update and general refactor
victordibia Nov 9, 2023
44e95b4
skills update
victordibia Nov 9, 2023
260fa78
general refactor
victordibia Nov 9, 2023
c0df418
ui folder structure refactor
victordibia Nov 9, 2023
bf228aa
improve support for skills loading
victordibia Nov 9, 2023
afddc69
add fetch profile default skill
victordibia Nov 12, 2023
ef40f42
refactor chat to autogenchat
victordibia Nov 12, 2023
7b89c52
qol refactor
victordibia Nov 12, 2023
aa626e0
improve metadata display
victordibia Nov 12, 2023
b05e370
early support for autogenflow in ui
victordibia Nov 13, 2023
1b90caa
Merge branch 'microsoft:main' into main
victordibia Nov 13, 2023
be5a343
docs update general refactor
victordibia Nov 13, 2023
132c633
general refactor
victordibia Nov 13, 2023
8236051
readme update
victordibia Nov 13, 2023
e7fc7ac
readme update
victordibia Nov 13, 2023
31f4b12
readme and cli update
victordibia Nov 13, 2023
c3ebc53
pre-commit updates
victordibia Nov 13, 2023
be4097c
precommit update
victordibia Nov 13, 2023
3634767
readme update
victordibia Nov 13, 2023
77e9c69
add steup.py for older python build versions
victordibia Nov 13, 2023
35602a0
add manifest.in, update app icon
victordibia Nov 13, 2023
bb047f4
in-progress changes to agent specification
victordibia Nov 13, 2023
c6b847b
remove use_cache refs
victordibia Nov 14, 2023
14b17bc
update datamodel, and fix for default serverurl
victordibia Nov 14, 2023
87f5d3e
request_timeout
victordibia Nov 14, 2023
b25d9f2
readme update, fix autogen values
victordibia Nov 14, 2023
88b6e15
fix pyautogen version
victordibia Nov 14, 2023
c9fbc62
precommit formatting and other qol items
victordibia Nov 14, 2023
6c68573
update folder structure
victordibia Nov 16, 2023
4b658c9
req update
victordibia Nov 16, 2023
1880214
Merge pull request #2 from pcdeadeasy/react-app
victordibia Nov 16, 2023
a55d63e
Merge branch 'microsoft:main' into main
victordibia Nov 16, 2023
a088345
readme and docs update
victordibia Nov 16, 2023
f1c7db0
docs update
victordibia Nov 16, 2023
adf2144
remove duplicate in yaml file
victordibia Nov 16, 2023
1aa3c9f
add support for explicit skills addition
victordibia Nov 16, 2023
f0d6894
readme and documentation updates
victordibia Nov 16, 2023
a6b7335
general refactor
victordibia Nov 16, 2023
a2f9a75
remove blog post, schedule for future PR
victordibia Nov 16, 2023
1a0f08d
Merge branch 'main' into main
victordibia Nov 16, 2023
60ad7d2
Merge branch 'main' into main
victordibia Nov 16, 2023
f783c5f
Merge branch 'main' into main
sonichi Nov 17, 2023
4e02a82
readme update, add info on llmconfig
victordibia Nov 17, 2023
a68bb4c
make use_cache False by default unless set
victordibia Nov 17, 2023
be200e3
minor ui updates
victordibia Nov 17, 2023
96bf235
upgrade ui to use latest uatogen lib version 0.2.0b5
victordibia Nov 20, 2023
fbafd7d
Ui refactor, support for adding arbitrary model specifications
victordibia Nov 20, 2023
bc35100
formatting/precommit checks
victordibia Nov 20, 2023
bac57d8
update readme, utils default skill
victordibia Nov 20, 2023
6ba704d
Merge branch 'main' of github.com:pcdeadeasy/autogen-oss into main
victordibia Nov 20, 2023
cc87058
Merge branch 'main' into main
victordibia Nov 20, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ branch = True
source = autogen
omit =
*test*
*samples*
24 changes: 24 additions & 0 deletions samples/apps/autogen-assistant/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
database.sqlite
.cache/*
autogenra/web/files/user/*
autogenra/web/files/ui/*
OAI_CONFIG_LIST
scratch/
autogenra/web/workdir/*
autogenra/web/ui/*
autogenra/web/skills/user/*
.release.sh

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
5 changes: 5 additions & 0 deletions samples/apps/autogen-assistant/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
recursive-include autogenra/web/ui *
recursive-exclude notebooks *
recursive-exclude frontend *
recursive-exclude docs *
recursive-exclude tests *
96 changes: 96 additions & 0 deletions samples/apps/autogen-assistant/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# AutoGen Assistant

![ARA](./docs/ara_stockprices.png)

AutoGen Assistant is an Autogen-powered AI app (user interface) that can converse with you to help you conduct research, write and execute code, run saved skills, learn new skills (explicitly and by demonstration), and adapt in response to your interactions.

Project Structure:

- _autogenra/_ code for the backend classes and web api (FastAPI)
- _frontend/_ code for the webui, built with Gatsby and Tailwind

## Getting Started

AutoGen requires access to an LLM. Please see the [AutoGen docs](https://microsoft.github.io/autogen/docs/FAQ#set-your-api-endpoints) on how to configure access to your LLM provider. In this sample, We recommend setting up your `OPENAI_API_KEY` environment variable and then specifying the exact model names to be used in the `llm_config` that is passed to each agent specification. See the `get_default_agent_config()` method in `utils.py` to see an example of setting up `llm_config`.
victordibia marked this conversation as resolved.
Show resolved Hide resolved

```bash
export OPENAI_API_KEY=<your_api_key>
```

### Install and Run

To install a prebuilt version of the app from PyPi. We highly recommend using a virtual environment (e.g. miniconda) and **python 3.10+** to avoid dependency conflicts.

```bash
pip install autogenra
autogenra ui --port 8081 # run the web ui on port 8081
```

### Install from Source

To install the app from source, clone the repository and install the dependencies.

```bash
pip install -e .
```

You will also need to build the app front end. Note that your Gatsby requires node > 14.15.0 . You may need to [upgrade your node](https://stackoverflow.com/questions/10075990/upgrading-node-js-to-latest-version) version as needed.

```bash
npm install --global yarn
cd frontend
yarn install
yarn build
```

The command above will build the frontend ui and copy the build artifacts to the `autogenra` web ui folder. Note that you may have to run `npm install --force --legacy-peer-deps` to force resolve some peer dependencies.

Run the web ui:

```bash
autogenra ui --port 8081 # run the web ui on port 8081
```

Navigate to <http://localhost:8081/> to view the web ui.

To update the web ui, navigate to the frontend directory, make changes and rebuild the ui.

## Capabilities

This demo focuses on the research assistant use case with some generalizations:

- **Skills**: The agent is provided with a list of skills that it can leverage while attempting to address a user's query. Each skill is a python function that may be in any file in a folder made availabe to the agents. We separate the concept of global skills available to all agents `backend/files/global_utlis_dir` and user level skills `backend/files/user/<user_hash>/utils_dir`, relevant in a multi user environment. Agents are aware skills as they are appended to the system message. A list of example skills is available in the `backend/global_utlis_dir` folder. Modify the file or create a new file with a function in the same directory to create new global skills.

- **Conversation Persistence**: Conversation history is persisted in an sqlite database `database.sqlite`.

- **Default Agent Workflow**: The default a sample workflow with two agents - a user proxy agent and an assistant agent.

## Example Usage

Let us use a simple query demonstrating the capabilities of the research assistant.

```
Plot a chart of NVDA and TESLA stock price YTD. Save the result to a file named nvda_tesla.png
```

The agents responds by _writing and executing code_ to create a python program to generate the chart with the stock prices.

> Note than there could be multiple turns between the `AssistantAgent` and the `UserProxyAgent` to produce and execute the code in order to complete the task.

![ARA](./docs/ara_stockprices.png)

> Note: You can also view the debug console that generates useful information to see how the agents are interacting in the background.

<!-- ![ARA](./docs/ara_console.png) -->

## FAQ

- How do I add more skills to the research assistant? This can be done by adding a new file with documented functions to `autogenra/web/skills/global` directory.
- How do I specify the agent configuration (e.g. temperature, model, agent system message, model etc). You can do either from the UI interface or by modifying the default agent configuration in `utils.py` (`get_default_agent_config()` method)
- How do I reset the conversation? You can reset the conversation by deleting the `database.sqlite` file. You can also delete user files by deleting the `autogenra/web/files/user/<user_id_md5hash>` folder.
- How do I view messages generated by agents? You can view the messages generated by the agents in the debug console. You can also view the messages in the `database.sqlite` file.

## Acknowledgements

Based on the [AutoGen](https://microsoft.github.io/autogen) project.
Adapted in October 2023 from a research prototype (original credits: Gagan Bansal, Adam Fourney, Victor Dibia, Piali Choudhury, Saleema Amershi, Ahmed Awadallah, Chi Wang)
Empty file.
64 changes: 64 additions & 0 deletions samples/apps/autogen-assistant/autogenra/autogenchat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import json
import time
from typing import List
from .datamodel import FlowConfig, Message
from .utils import extract_successful_code_blocks, get_default_agent_config, get_modified_files
from .autogenflow import AutoGenFlow
import os


class ChatManager:
def __init__(self) -> None:
pass

def chat(self, message: Message, history: List, flow_config: FlowConfig = None, **kwargs) -> None:
work_dir = kwargs.get("work_dir", None)
scratch_dir = os.path.join(work_dir, "scratch")
skills_suffix = kwargs.get("skills_prompt", "")

# if no flow config is provided, use the default
if flow_config is None:
flow_config = get_default_agent_config(scratch_dir, skills_suffix=skills_suffix)

# print("Flow config: ", flow_config)
flow = AutoGenFlow(config=flow_config, history=history, work_dir=scratch_dir, asst_prompt=skills_suffix)
message_text = message.content.strip()

output = ""
start_time = time.time()

metadata = {}
flow.run(message=f"{message_text}", clear_history=False)

agent_chat_messages = flow.receiver.chat_messages[flow.sender][len(history) :]
metadata["messages"] = agent_chat_messages

successful_code_blocks = extract_successful_code_blocks(agent_chat_messages)
successful_code_blocks = "\n\n".join(successful_code_blocks)
output = (
(
flow.sender.last_message()["content"]
+ "\n The following code snippets were used: \n"
+ successful_code_blocks
)
if successful_code_blocks
else flow.sender.last_message()["content"]
)

metadata["code"] = ""
end_time = time.time()
metadata["time"] = end_time - start_time
modified_files = get_modified_files(start_time, end_time, scratch_dir, dest_dir=work_dir)
metadata["files"] = modified_files

print("Modified files: ", modified_files)

output_message = Message(
user_id=message.user_id,
root_msg_id=message.root_msg_id,
role="assistant",
content=output,
metadata=json.dumps(metadata),
)

return output_message
133 changes: 133 additions & 0 deletions samples/apps/autogen-assistant/autogenra/autogenflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
from typing import List, Optional
from dataclasses import asdict
import autogen
from .datamodel import AgentFlowSpec, FlowConfig, Message


class AutoGenFlow:
"""
AutoGenFlow class to load agents from a provided configuration and run a chat between them
"""

def __init__(
self, config: FlowConfig, history: Optional[List[Message]] = None, work_dir: str = None, asst_prompt: str = None
) -> None:
"""
Initializes the AutoGenFlow with agents specified in the config and optional
message history.

Args:
config: The configuration settings for the sender and receiver agents.
history: An optional list of previous messages to populate the agents' history.

"""
self.work_dir = work_dir
self.asst_prompt = asst_prompt
self.sender = self.load(config.sender)
self.receiver = self.load(config.receiver)

if history:
self.populate_history(history)

def _sanitize_history_message(self, message: str) -> str:
"""
Sanitizes the message e.g. remove references to execution completed

Args:
message: The message to be sanitized.

Returns:
The sanitized message.
"""
to_replace = ["execution succeeded", "exitcode"]
for replace in to_replace:
message = message.replace(replace, "")
return message

def populate_history(self, history: List[Message]) -> None:
"""
Populates the agent message history from the provided list of messages.

Args:
history: A list of messages to populate the agents' history.
"""
for msg in history:
if isinstance(msg, dict):
msg = Message(**msg)
if msg.role == "user":
self.sender.send(
msg.content,
self.receiver,
request_reply=False,
)
elif msg.role == "assistant":
self.receiver.send(
msg.content,
self.sender,
request_reply=False,
)

def sanitize_agent_spec(self, agent_spec: AgentFlowSpec) -> AgentFlowSpec:
"""
Sanitizes the agent spec by setting loading defaults

Args:
config: The agent configuration to be sanitized.
agent_type: The type of the agent.

Returns:
The sanitized agent configuration.
"""

agent_spec.config.is_termination_msg = agent_spec.config.is_termination_msg or (
lambda x: "TERMINATE" in x.get("content", "").rstrip()
)

if agent_spec.type == "userproxy":
code_execution_config = agent_spec.config.code_execution_config or {}
code_execution_config["work_dir"] = self.work_dir
agent_spec.config.code_execution_config = code_execution_config
if agent_spec.type == "assistant":
agent_spec.config.system_message = (
autogen.AssistantAgent.DEFAULT_SYSTEM_MESSAGE
+ "\n\n"
+ agent_spec.config.system_message
+ "\n\n"
+ self.asst_prompt
)
return agent_spec

def load(self, agent_spec: AgentFlowSpec) -> autogen.Agent:
"""
Loads an agent based on the provided agent specification.

Args:
agent_spec: The specification of the agent to be loaded.

Returns:
An instance of the loaded agent.
"""
agent: autogen.Agent
agent_spec = self.sanitize_agent_spec(agent_spec)
if agent_spec.type == "assistant":
agent = autogen.AssistantAgent(**asdict(agent_spec.config))
elif agent_spec.type == "userproxy":
agent = autogen.UserProxyAgent(**asdict(agent_spec.config))
else:
raise ValueError(f"Unknown agent type: {agent_spec.type}")
return agent

def run(self, message: str, clear_history: bool = False) -> None:
"""
Initiates a chat between the sender and receiver agents with an initial message
and an option to clear the history.

Args:
message: The initial message to start the chat.
clear_history: If set to True, clears the chat history before initiating.
"""
self.sender.initiate_chat(
self.receiver,
message=message,
clear_history=clear_history,
)
48 changes: 48 additions & 0 deletions samples/apps/autogen-assistant/autogenra/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os
from typing_extensions import Annotated
import typer
import uvicorn

from .version import VERSION

app = typer.Typer()


@app.command()
def ui(
host: str = "127.0.0.1",
port: int = 8081,
workers: int = 1,
reload: Annotated[bool, typer.Option("--reload")] = False,
docs: bool = False,
):
"""
Launch the Autogen RA UI CLI .Pass in parameters host, port, workers, and reload to override the default values.
"""

os.environ["AUTOGENUI_API_DOCS"] = str(docs)

uvicorn.run(
"autogenra.web.app:app",
host=host,
port=port,
workers=workers,
reload=reload,
)


@app.command()
def version():
"""
Print the version of the Autogen RA UI CLI.
"""

typer.echo(f"Autogen RA UI CLI version: {VERSION}")


def run():
app()


if __name__ == "__main__":
app()
Loading
Loading