From effd58601701f24dc5743bd8a57f8cf3f52185fa Mon Sep 17 00:00:00 2001 From: Victor Dibia Date: Fri, 15 Dec 2023 20:04:12 -0800 Subject: [PATCH 01/21] add new autogen-studio renamed folder --- samples/apps/autogen-studio/.gitignore | 24 + samples/apps/autogen-studio/MANIFEST.in | 5 + samples/apps/autogen-studio/README.md | 122 ++ .../autogen-studio/autogenstudio/__init__.py | 3 + .../autogenstudio/chatmanager.py | 65 + .../apps/autogen-studio/autogenstudio/cli.py | 48 + .../autogen-studio/autogenstudio/datamodel.py | 227 +++ .../autogenstudio/utils/__init__.py | 2 + .../autogenstudio/utils/dbdefaults.json | 189 +++ .../autogenstudio/utils/dbutils.py | 562 +++++++ .../autogenstudio/utils/utils.py | 492 ++++++ .../autogen-studio/autogenstudio/version.py | 2 + .../autogenstudio/web/__init__.py | 0 .../autogen-studio/autogenstudio/web/app.py | 362 +++++ .../autogenstudio/workflowmanager.py | 143 ++ .../autogen-studio/docs/ara_stockprices.png | Bin 0 -> 198222 bytes .../apps/autogen-studio/frontend/.env.default | 5 + .../apps/autogen-studio/frontend/.gitignore | 8 + samples/apps/autogen-studio/frontend/LICENSE | 21 + .../apps/autogen-studio/frontend/README.md | 30 + .../autogen-studio/frontend/gatsby-browser.js | 6 + .../autogen-studio/frontend/gatsby-config.ts | 52 + .../autogen-studio/frontend/gatsby-ssr.tsx | 16 + .../apps/autogen-studio/frontend/package.json | 65 + .../autogen-studio/frontend/postcss.config.js | 4 + .../frontend/src/components/atoms.tsx | 1350 +++++++++++++++++ .../frontend/src/components/footer.tsx | 26 + .../frontend/src/components/header.tsx | 274 ++++ .../frontend/src/components/icons.tsx | 205 +++ .../frontend/src/components/layout.tsx | 57 + .../frontend/src/components/types.ts | 102 ++ .../frontend/src/components/utils.ts | 403 +++++ .../src/components/views/builder/agents.tsx | 276 ++++ .../src/components/views/builder/build.tsx | 37 + .../src/components/views/builder/skills.tsx | 241 +++ .../src/components/views/builder/workflow.tsx | 275 ++++ .../src/components/views/gallery/gallery.tsx | 208 +++ .../components/views/playground/chatbox.tsx | 491 ++++++ .../components/views/playground/metadata.tsx | 164 ++ .../src/components/views/playground/ra.tsx | 87 ++ .../components/views/playground/sessions.tsx | 255 ++++ .../components/views/playground/sidebar.tsx | 53 + .../components/views/playground/workflows.tsx | 114 ++ .../frontend/src/hooks/provider.tsx | 73 + .../frontend/src/hooks/store.tsx | 25 + .../frontend/src/images/icon.png | Bin 0 -> 12710 bytes .../autogen-studio/frontend/src/pages/404.tsx | 54 + .../frontend/src/pages/build.tsx | 28 + .../frontend/src/pages/gallery/index.tsx | 28 + .../frontend/src/pages/index.tsx | 28 + .../frontend/src/styles/global.css | 347 +++++ .../frontend/tailwind.config.js | 36 + .../autogen-studio/frontend/tsconfig.json | 20 + .../autogen-studio/notebooks/agent_spec.json | 44 + .../autogen-studio/notebooks/tutorial.ipynb | 87 ++ samples/apps/autogen-studio/pyproject.toml | 61 + samples/apps/autogen-studio/requirements.txt | 1 + samples/apps/autogen-studio/setup.py | 3 + 58 files changed, 7906 insertions(+) create mode 100644 samples/apps/autogen-studio/.gitignore create mode 100644 samples/apps/autogen-studio/MANIFEST.in create mode 100644 samples/apps/autogen-studio/README.md create mode 100644 samples/apps/autogen-studio/autogenstudio/__init__.py create mode 100644 samples/apps/autogen-studio/autogenstudio/chatmanager.py create mode 100644 samples/apps/autogen-studio/autogenstudio/cli.py create mode 100644 samples/apps/autogen-studio/autogenstudio/datamodel.py create mode 100644 samples/apps/autogen-studio/autogenstudio/utils/__init__.py create mode 100644 samples/apps/autogen-studio/autogenstudio/utils/dbdefaults.json create mode 100644 samples/apps/autogen-studio/autogenstudio/utils/dbutils.py create mode 100644 samples/apps/autogen-studio/autogenstudio/utils/utils.py create mode 100644 samples/apps/autogen-studio/autogenstudio/version.py create mode 100644 samples/apps/autogen-studio/autogenstudio/web/__init__.py create mode 100644 samples/apps/autogen-studio/autogenstudio/web/app.py create mode 100644 samples/apps/autogen-studio/autogenstudio/workflowmanager.py create mode 100644 samples/apps/autogen-studio/docs/ara_stockprices.png create mode 100644 samples/apps/autogen-studio/frontend/.env.default create mode 100644 samples/apps/autogen-studio/frontend/.gitignore create mode 100644 samples/apps/autogen-studio/frontend/LICENSE create mode 100644 samples/apps/autogen-studio/frontend/README.md create mode 100644 samples/apps/autogen-studio/frontend/gatsby-browser.js create mode 100644 samples/apps/autogen-studio/frontend/gatsby-config.ts create mode 100644 samples/apps/autogen-studio/frontend/gatsby-ssr.tsx create mode 100644 samples/apps/autogen-studio/frontend/package.json create mode 100644 samples/apps/autogen-studio/frontend/postcss.config.js create mode 100644 samples/apps/autogen-studio/frontend/src/components/atoms.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/footer.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/header.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/icons.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/layout.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/types.ts create mode 100644 samples/apps/autogen-studio/frontend/src/components/utils.ts create mode 100644 samples/apps/autogen-studio/frontend/src/components/views/builder/agents.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/views/builder/build.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/views/builder/skills.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/views/builder/workflow.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/views/gallery/gallery.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/views/playground/chatbox.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/views/playground/metadata.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/views/playground/ra.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/views/playground/sessions.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/views/playground/sidebar.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/components/views/playground/workflows.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/hooks/provider.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/hooks/store.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/images/icon.png create mode 100644 samples/apps/autogen-studio/frontend/src/pages/404.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/pages/build.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/pages/gallery/index.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/pages/index.tsx create mode 100644 samples/apps/autogen-studio/frontend/src/styles/global.css create mode 100644 samples/apps/autogen-studio/frontend/tailwind.config.js create mode 100644 samples/apps/autogen-studio/frontend/tsconfig.json create mode 100644 samples/apps/autogen-studio/notebooks/agent_spec.json create mode 100644 samples/apps/autogen-studio/notebooks/tutorial.ipynb create mode 100644 samples/apps/autogen-studio/pyproject.toml create mode 100644 samples/apps/autogen-studio/requirements.txt create mode 100644 samples/apps/autogen-studio/setup.py diff --git a/samples/apps/autogen-studio/.gitignore b/samples/apps/autogen-studio/.gitignore new file mode 100644 index 000000000000..e94e41454a85 --- /dev/null +++ b/samples/apps/autogen-studio/.gitignore @@ -0,0 +1,24 @@ +database.sqlite +.cache/* +autogenstudio/web/files/user/* +autogenstudio/web/files/ui/* +OAI_CONFIG_LIST +scratch/ +autogenstudio/web/workdir/* +autogenstudio/web/ui/* +autogenstudio/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/ diff --git a/samples/apps/autogen-studio/MANIFEST.in b/samples/apps/autogen-studio/MANIFEST.in new file mode 100644 index 000000000000..6406a9240a6b --- /dev/null +++ b/samples/apps/autogen-studio/MANIFEST.in @@ -0,0 +1,5 @@ +recursive-include autogenstudio/web/ui * +recursive-exclude notebooks * +recursive-exclude frontend * +recursive-exclude docs * +recursive-exclude tests * diff --git a/samples/apps/autogen-studio/README.md b/samples/apps/autogen-studio/README.md new file mode 100644 index 000000000000..f100dd4396fd --- /dev/null +++ b/samples/apps/autogen-studio/README.md @@ -0,0 +1,122 @@ +# AutoGen Studio + +![ARA](./docs/ara_stockprices.png) + +AutoGen Studio is an AutoGen-powered AI app (user interface) to help you rapidly prototype AI agents, enhance them with skills, compose them into workflows and interact with them to accomplish tasks. It is built on top of the [AutoGen](https://microsoft.github.io/autogen) framework, which is a toolkit for building AI agents. + +Code for AutoGen Studio is on GitHub at [microsoft/autogen](https://github.com/microsoft/autogen/tree/main/samples/apps/autogen-studio) + +> **Note**: AutoGen Studio is meant to be an example/guide of how to build an AI app using the AutoGen framework. It is not meant to be a production-ready app. + +### Capabilities / Roadmap + +Some of the capabilities supported by the app frontend include the following: + +- [x] Build / Configure agents (currently supports two agent workflows based on `UserProxyAgent` and `AssistantAgent`), modify their configuration (e.g. skills, temperature, model, agent system message, model etc) and compose them into workflows. +- [x] Chat with agent works and specify tasks. +- [x] View agent messages and output files in the UI from agent runs. +- [x] Add interaction sessions to a gallery. +- [ ] Support for more complex agent workflows (e.g. `GroupChat` workflows). +- [ ] Improved user experience (e.g., streaming intermediate model output, better summarization of agent responses, etc). + +Project Structure: + +- _autogenstudio/_ code for the backend classes and web api (FastAPI) +- _frontend/_ code for the webui, built with Gatsby and TailwindCSS + +### Installation + +1. **Install from PyPi** + + We recommend using a virtual environment (e.g., conda) to avoid conflicts with existing Python packages. With Python 3.10 or newer active in your virtual environment, use pip to install AutoGen Studio: + + ```bash + pip install autogenstudio + ``` + +2. **Install from Source** + + > Note: This approach requires some familiarity with building interfaces in React. + + If you prefer to install from source, ensure you have Python 3.10+ and Node.js (version above 14.15.0) installed. Here's how you get started: + + - Clone the AutoGen Studio repository and install its Python dependencies: + + ```bash + pip install -e . + ``` + + - Navigate to the `samples/apps/autogen-assistant/frontend` directory, install dependencies, and build the UI: + + ```bash + npm install -g gatsby-cli + npm install --global yarn + cd frontend + yarn install + yarn build + ``` + +For Windows users, to build the frontend, you may need alternative commands to build the frontend. + +```bash + + gatsby clean && rmdir /s /q ..\\autogenstudio\\web\\ui && (set \"PREFIX_PATH_VALUE=\" || ver>nul) && gatsby build --prefix-paths && xcopy /E /I /Y public ..\\autogenstudio\\web\\ui + +``` + +### Running the Application + +Once installed, run the web UI by entering the following in your terminal: + +```bash +autogenstudio ui --port 8081 +``` + +This will start the application on the specified port. Open your web browser and go to `http://localhost:8081/` to begin using AutoGen Studio. + +Now that you have AutoGen Studio installed and running, you are ready to explore its capabilities, including defining and modifying agent workflows, interacting with agents and sessions, and expanding agent skills. + +## Capabilities + +AutoGen Studio proposes some high-level concepts. + +**Agent Workflow**: An agent workflow is a specification of a set of agents that can work together to accomplish a task. The simplest version of this is a setup with two agents – a user proxy agent (that represents a user i.e. it compiles code and prints result) and an assistant that can address task requests (e.g., generating plans, writing code, evaluating responses, proposing error recovery steps, etc.). A more complex flow could be a group chat where even more agents work towards a solution. + +**Session**: A session refers to a period of continuous interaction or engagement with an agent workflow, typically characterized by a sequence of activities or operations aimed at achieving specific objectives. It includes the agent workflow configuration, the interactions between the user and the agents. A session can be “published” to a “gallery”. + +**Skills**: Skills are functions (e.g., Python functions) that describe how to solve a task. In general, a good skill has a descriptive name (e.g. `generate_images`), extensive docstrings and good defaults (e.g., writing out files to disk for persistence and reuse). You can add new skills AutoGen Studio app via the provided UI. At inference time, these skills are made available to the assistant agent as they address your tasks. + +AutoGen Studio comes with 3 example skills: `fetch_profile`, `find_papers`, `generate_images`. The default skills, agents and workflows are based on the [dbdefaults.json](autogentstudio/utils/dbdefaults.json) file which is used to initialize the database. + +## Example Usage + +Consider the following query. + +``` +Plot a chart of NVDA and TESLA stock price YTD. Save the result to a file named nvda_tesla.png +``` + +The agent workflow 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. + + + +## FAQ + +**Q: Where can I adjust the default skills, agent and workflow configurations?** +A: You can modify agent configurations directly from the UI or by editing the [dbdefaults.json](autogentstudio/utils/dbdefaults.json) file which is used to initialize the database. + +**Q: If I want to reset the entire conversation with an agent, how do I go about it?** +A: To reset your conversation history, you can delete the `database.sqlite` file. If you need to clear user-specific data, remove the relevant `autogenstudio/web/files/user/` folder. + +**Q: Is it possible to view the output and messages generated by the agents during interactions?** +A: Yes, you can view the generated messages in the debug console of the web UI, providing insights into the agent interactions. Alternatively, you can inspect the `database.sqlite` file for a comprehensive record of messages. + +## Acknowledgements + +AutoGen Studio is Based on the [AutoGen](https://microsoft.github.io/autogen) project. It was adapted from a research prototype built in October 2023 (original credits: Gagan Bansal, Adam Fourney, Victor Dibia, Piali Choudhury, Saleema Amershi, Ahmed Awadallah, Chi Wang). diff --git a/samples/apps/autogen-studio/autogenstudio/__init__.py b/samples/apps/autogen-studio/autogenstudio/__init__.py new file mode 100644 index 000000000000..784328a73bd5 --- /dev/null +++ b/samples/apps/autogen-studio/autogenstudio/__init__.py @@ -0,0 +1,3 @@ +from .chatmanager import * +from .workflowmanager import * +from .datamodel import * diff --git a/samples/apps/autogen-studio/autogenstudio/chatmanager.py b/samples/apps/autogen-studio/autogenstudio/chatmanager.py new file mode 100644 index 000000000000..a0c71c01b259 --- /dev/null +++ b/samples/apps/autogen-studio/autogenstudio/chatmanager.py @@ -0,0 +1,65 @@ +import json +import time +from typing import List +from .datamodel import AgentWorkFlowConfig, Message +from .utils import extract_successful_code_blocks, get_default_agent_config, get_modified_files +from .workflowmanager import AutoGenWorkFlowManager +import os + + +class AutoGenChatManager: + def __init__(self) -> None: + pass + + def chat(self, message: Message, history: List, flow_config: AgentWorkFlowConfig = None, **kwargs) -> None: + work_dir = kwargs.get("work_dir", None) + scratch_dir = os.path.join(work_dir, "scratch") + + # if no flow config is provided, use the default + if flow_config is None: + flow_config = get_default_agent_config(scratch_dir) + + # print("Flow config: ", flow_config) + flow = AutoGenWorkFlowManager( + config=flow_config, history=history, work_dir=scratch_dir) + 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" + 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: ", len(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), + session_id=message.session_id, + ) + + return output_message diff --git a/samples/apps/autogen-studio/autogenstudio/cli.py b/samples/apps/autogen-studio/autogenstudio/cli.py new file mode 100644 index 000000000000..22692700ff06 --- /dev/null +++ b/samples/apps/autogen-studio/autogenstudio/cli.py @@ -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 Studio UI CLI .Pass in parameters host, port, workers, and reload to override the default values. + """ + + os.environ["AUTOGENUI_API_DOCS"] = str(docs) + + uvicorn.run( + "autogenstudio.web.app:app", + host=host, + port=port, + workers=workers, + reload=reload, + ) + + +@app.command() +def version(): + """ + Print the version of the AutoGen Studio UI CLI. + """ + + typer.echo(f"AutoGen Studio UI CLI version: {VERSION}") + + +def run(): + app() + + +if __name__ == "__main__": + app() diff --git a/samples/apps/autogen-studio/autogenstudio/datamodel.py b/samples/apps/autogen-studio/autogenstudio/datamodel.py new file mode 100644 index 000000000000..7fae90ee5778 --- /dev/null +++ b/samples/apps/autogen-studio/autogenstudio/datamodel.py @@ -0,0 +1,227 @@ +import uuid +from datetime import datetime +from typing import Any, Callable, Dict, List, Literal, Optional, Union +from pydantic.dataclasses import dataclass +from dataclasses import asdict, field + + +@dataclass +class Message(object): + user_id: str + role: str + content: str + root_msg_id: Optional[str] = None + msg_id: Optional[str] = None + timestamp: Optional[str] = None + personalize: Optional[bool] = False + ra: Optional[str] = None + code: Optional[str] = None + metadata: Optional[Any] = None + session_id: Optional[str] = None + + def __post_init__(self): + if self.msg_id is None: + self.msg_id = str(uuid.uuid4()) + if self.timestamp is None: + self.timestamp = datetime.now().isoformat() + + def dict(self): + result = asdict(self) + return result + + +@dataclass +class Skill(object): + title: str + file_name: str + content: str + id: Optional[str] = None + description: Optional[str] = None + timestamp: Optional[str] = None + user_id: Optional[str] = None + + def __post_init__(self): + if self.id is None: + self.id = str(uuid.uuid4()) + if self.timestamp is None: + self.timestamp = datetime.now().isoformat() + if self.user_id is None: + self.user_id = "default" + + def dict(self): + result = asdict(self) + return result + + +# web api data models + + +# autogenflow data models +@dataclass +class ModelConfig: + """Data model for Model Config item in LLMConfig for AutoGen""" + + model: str + api_key: Optional[str] = None + base_url: Optional[str] = None + api_type: Optional[str] = None + api_version: Optional[str] = None + + +@dataclass +class LLMConfig: + """Data model for LLM Config for AutoGen""" + + config_list: List[Any] = field(default_factory=List) + temperature: float = 0 + cache_seed: Optional[Union[int, None]] = None + timeout: Optional[int] = None + + +@dataclass +class AgentConfig: + """Data model for Agent Config for AutoGen""" + + name: str + llm_config: Optional[Union[LLMConfig, bool]] = False + human_input_mode: str = "NEVER" + max_consecutive_auto_reply: int = 10 + system_message: Optional[str] = None + is_termination_msg: Optional[Union[bool, str, Callable]] = None + code_execution_config: Optional[Union[bool, str, Dict[str, Any]]] = None + + def dict(self): + result = asdict(self) + if isinstance(result["llm_config"], LLMConfig): + result["llm_config"] = result["llm_config"].dict() + return result + + +@dataclass +class AgentFlowSpec: + """Data model to help flow load agents from config""" + + type: Literal["assistant", "userproxy", "groupchat"] + config: AgentConfig = field(default_factory=AgentConfig) + id: Optional[str] = None + timestamp: Optional[str] = None + user_id: Optional[str] = None + skills: Optional[Union[None, List[Skill]]] = None + description: Optional[str] = None + + def __post_init__(self): + if self.timestamp is None: + self.timestamp = datetime.now().isoformat() + if self.id is None: + self.id = str(uuid.uuid4()) + if self.user_id is None: + self.user_id = "default" + + def dict(self): + result = asdict(self) + return result + + +@dataclass +class AgentWorkFlowConfig: + """Data model for Flow Config for AutoGen""" + + name: str + description: str + sender: AgentFlowSpec + receiver: Union[AgentFlowSpec, List[AgentFlowSpec]] + type: Literal["default", "groupchat"] = "default" + id: Optional[str] = None + user_id: Optional[str] = None + timestamp: Optional[str] = None + + def __post_init__(self): + if self.id is None: + self.id = str(uuid.uuid4()) + if self.user_id is None: + self.user_id = "default" + if self.timestamp is None: + self.timestamp = datetime.now().isoformat() + + def dict(self): + result = asdict(self) + result["sender"] = self.sender.dict() + if isinstance(self.receiver, list): + result["receiver"] = [r.dict() for r in self.receiver] + else: + result["receiver"] = self.receiver.dict() + return result + + +@dataclass +class Session(object): + """Data model for AutoGen Chat Session""" + + user_id: str + id: Optional[str] = None + timestamp: Optional[str] = None + flow_config: AgentWorkFlowConfig = None + + def __post_init__(self): + if self.timestamp is None: + self.timestamp = datetime.now().isoformat() + if self.id is None: + self.id = str(uuid.uuid4()) + + def dict(self): + result = asdict(self) + result["flow_config"] = self.flow_config.dict() + return result + + +@dataclass +class Gallery(object): + """Data model for Gallery Item""" + + session: Session + messages: List[Message] + tags: List[str] + id: Optional[str] = None + timestamp: Optional[str] = None + + def __post_init__(self): + if self.timestamp is None: + self.timestamp = datetime.now().isoformat() + if self.id is None: + self.id = str(uuid.uuid4()) + + def dict(self): + result = asdict(self) + return result + + +@dataclass +class ChatWebRequestModel(object): + """Data model for Chat Web Request for Web End""" + + message: Message + flow_config: AgentWorkFlowConfig + + +@dataclass +class DeleteMessageWebRequestModel(object): + user_id: str + msg_id: str + session_id: Optional[str] = None + + +@dataclass +class CreateSkillWebRequestModel(object): + user_id: str + skill: Skill + + +@dataclass +class DBWebRequestModel(object): + user_id: str + msg_id: Optional[str] = None + session: Optional[Session] = None + skills: Optional[Union[str, List[str]]] = None + tags: Optional[List[str]] = None + agent: Optional[AgentFlowSpec] = None + workflow: Optional[AgentWorkFlowConfig] = None diff --git a/samples/apps/autogen-studio/autogenstudio/utils/__init__.py b/samples/apps/autogen-studio/autogenstudio/utils/__init__.py new file mode 100644 index 000000000000..f37b0b0486a2 --- /dev/null +++ b/samples/apps/autogen-studio/autogenstudio/utils/__init__.py @@ -0,0 +1,2 @@ +from .dbutils import * +from .utils import * diff --git a/samples/apps/autogen-studio/autogenstudio/utils/dbdefaults.json b/samples/apps/autogen-studio/autogenstudio/utils/dbdefaults.json new file mode 100644 index 000000000000..69ebcfafb212 --- /dev/null +++ b/samples/apps/autogen-studio/autogenstudio/utils/dbdefaults.json @@ -0,0 +1,189 @@ +{ + "agents": [ + { + "type": "userproxy", + "description": "A user proxy agent that executes code.", + "config": { + "name": "userproxy", + "human_input_mode": "NEVER", + "max_consecutive_auto_reply": 5, + "system_message": "", + "llm_config": false, + "code_execution_config": { + "work_dir": null, + "use_docker": false + } + } + }, + { + "type": "assistant", + "description": "A primary assistant agent that writes plans and code to solve tasks.", + "skills": [ + { + "title": "find_papers_arxiv", + "description": "This skill finds relevant papers on arXiv given a query.", + "content": "import os\nimport re\nimport json\nimport hashlib\n\n\ndef search_arxiv(query, max_results=10):\n \"\"\"\n Searches arXiv for the given query using the arXiv API, then returns the search results. This is a helper function. In most cases, callers will want to use 'find_relevant_papers( query, max_results )' instead.\n\n Args:\n query (str): The search query.\n max_results (int, optional): The maximum number of search results to return. Defaults to 10.\n\n Returns:\n jresults (list): A list of dictionaries. Each dictionary contains fields such as 'title', 'authors', 'summary', and 'pdf_url'\n\n Example:\n >>> results = search_arxiv(\"attention is all you need\")\n >>> print(results)\n \"\"\"\n\n import arxiv\n\n key = hashlib.md5((\"search_arxiv(\" + str(max_results) + \")\" + query).encode(\"utf-8\")).hexdigest()\n # Create the cache if it doesn't exist\n cache_dir = \".cache\"\n if not os.path.isdir(cache_dir):\n os.mkdir(cache_dir)\n\n fname = os.path.join(cache_dir, key + \".cache\")\n\n # Cache hit\n if os.path.isfile(fname):\n fh = open(fname, \"r\", encoding=\"utf-8\")\n data = json.loads(fh.read())\n fh.close()\n return data\n\n # Normalize the query, removing operator keywords\n query = re.sub(r\"[^\\s\\w]\", \" \", query.lower())\n query = re.sub(r\"\\s(and|or|not)\\s\", \" \", \" \" + query + \" \")\n query = re.sub(r\"[^\\s\\w]\", \" \", query.lower())\n query = re.sub(r\"\\s+\", \" \", query).strip()\n\n search = arxiv.Search(query=query, max_results=max_results, sort_by=arxiv.SortCriterion.Relevance)\n\n jresults = list()\n for result in search.results():\n r = dict()\n r[\"entry_id\"] = result.entry_id\n r[\"updated\"] = str(result.updated)\n r[\"published\"] = str(result.published)\n r[\"title\"] = result.title\n r[\"authors\"] = [str(a) for a in result.authors]\n r[\"summary\"] = result.summary\n r[\"comment\"] = result.comment\n r[\"journal_ref\"] = result.journal_ref\n r[\"doi\"] = result.doi\n r[\"primary_category\"] = result.primary_category\n r[\"categories\"] = result.categories\n r[\"links\"] = [str(link) for link in result.links]\n r[\"pdf_url\"] = result.pdf_url\n jresults.append(r)\n\n if len(jresults) > max_results:\n jresults = jresults[0:max_results]\n\n # Save to cache\n fh = open(fname, \"w\")\n fh.write(json.dumps(jresults))\n fh.close()\n return jresults\n", + "file_name": "find_papers_arxiv.py" + }, + { + "title": "generate_images", + "description": "This skill generates images from a given query using OpenAI's DALL-E model and saves them to disk.", + "content": "from typing import List\nimport uuid\nimport requests # to perform HTTP requests\nfrom pathlib import Path\n\nfrom openai import OpenAI\n\n\ndef generate_and_save_images(query: str, image_size: str = \"1024x1024\") -> List[str]:\n \"\"\"\n Function to paint, draw or illustrate images based on the users query or request. Generates images from a given query using OpenAI's DALL-E model and saves them to disk. Use the code below anytime there is a request to create an image.\n\n :param query: A natural language description of the image to be generated.\n :param image_size: The size of the image to be generated. (default is \"1024x1024\")\n :return: A list of filenames for the saved images.\n \"\"\"\n\n client = OpenAI() # Initialize the OpenAI client\n response = client.images.generate(model=\"dall-e-3\", prompt=query, n=1, size=image_size) # Generate images\n\n # List to store the file names of saved images\n saved_files = []\n\n # Check if the response is successful\n if response.data:\n for image_data in response.data:\n # Generate a random UUID as the file name\n file_name = str(uuid.uuid4()) + \".png\" # Assuming the image is a PNG\n file_path = Path(file_name)\n\n img_url = image_data.url\n img_response = requests.get(img_url)\n if img_response.status_code == 200:\n # Write the binary content to a file\n with open(file_path, \"wb\") as img_file:\n img_file.write(img_response.content)\n print(f\"Image saved to {file_path}\")\n saved_files.append(str(file_path))\n else:\n print(f\"Failed to download the image from {img_url}\")\n else:\n print(\"No image data found in the response!\")\n\n # Return the list of saved files\n return saved_files\n\n\n# Example usage of the function:\n# generate_and_save_images(\"A cute baby sea otter\")\n", + "file_name": "generate_images.py" + } + ], + "config": { + "name": "primary_assistant", + "llm_config": { + "config_list": [ + { + "model": "gpt-4-1106-preview" + }, + { + "model": "gpt-3.5-turbo-16k" + }, + { + "model": "TheBloke/zephyr-7B-alpha-AWQ", + "base_url": "http://localhost:8000/v1" + } + ], + "temperature": 0.1, + "timeout": 600, + "cache_seed": null + }, + "human_input_mode": "NEVER", + "max_consecutive_auto_reply": 8, + "system_message": "You are a helpful assistant that can use available functions when needed to solve problems. At each point, do your best to determine if the user's request has been addressed. IF THE REQUEST HAS NOT BEEN ADDRESSED, RESPOND WITH CODE TO ADDRESS IT. IF A FAILURE OCCURRED (e.g., due to a missing library) AND SOME ADDITIONAL CODE WAS WRITTEN (e.g. code to install the library), ENSURE THAT THE ORIGINAL CODE TO ADDRESS THE TASK STILL GETS EXECUTED. If the request HAS been addressed, respond with a summary of the result. The summary must be written as a coherent helpful response to the user request e.g. 'Sure, here is result to your request ' or 'The tallest mountain in Africa is ..' etc. The summary MUST end with the word TERMINATE. If the user request is pleasantry or greeting, you should respond with a pleasantry or greeting and TERMINATE." + } + } + ], + "skills": [ + { + "title": "find_papers_arxiv", + "description": "This skill finds relevant papers on arXiv given a query.", + "content": "import os\nimport re\nimport json\nimport hashlib\n\n\ndef search_arxiv(query, max_results=10):\n \"\"\"\n Searches arXiv for the given query using the arXiv API, then returns the search results. This is a helper function. In most cases, callers will want to use 'find_relevant_papers( query, max_results )' instead.\n\n Args:\n query (str): The search query.\n max_results (int, optional): The maximum number of search results to return. Defaults to 10.\n\n Returns:\n jresults (list): A list of dictionaries. Each dictionary contains fields such as 'title', 'authors', 'summary', and 'pdf_url'\n\n Example:\n >>> results = search_arxiv(\"attention is all you need\")\n >>> print(results)\n \"\"\"\n\n import arxiv\n\n key = hashlib.md5((\"search_arxiv(\" + str(max_results) + \")\" + query).encode(\"utf-8\")).hexdigest()\n # Create the cache if it doesn't exist\n cache_dir = \".cache\"\n if not os.path.isdir(cache_dir):\n os.mkdir(cache_dir)\n\n fname = os.path.join(cache_dir, key + \".cache\")\n\n # Cache hit\n if os.path.isfile(fname):\n fh = open(fname, \"r\", encoding=\"utf-8\")\n data = json.loads(fh.read())\n fh.close()\n return data\n\n # Normalize the query, removing operator keywords\n query = re.sub(r\"[^\\s\\w]\", \" \", query.lower())\n query = re.sub(r\"\\s(and|or|not)\\s\", \" \", \" \" + query + \" \")\n query = re.sub(r\"[^\\s\\w]\", \" \", query.lower())\n query = re.sub(r\"\\s+\", \" \", query).strip()\n\n search = arxiv.Search(query=query, max_results=max_results, sort_by=arxiv.SortCriterion.Relevance)\n\n jresults = list()\n for result in search.results():\n r = dict()\n r[\"entry_id\"] = result.entry_id\n r[\"updated\"] = str(result.updated)\n r[\"published\"] = str(result.published)\n r[\"title\"] = result.title\n r[\"authors\"] = [str(a) for a in result.authors]\n r[\"summary\"] = result.summary\n r[\"comment\"] = result.comment\n r[\"journal_ref\"] = result.journal_ref\n r[\"doi\"] = result.doi\n r[\"primary_category\"] = result.primary_category\n r[\"categories\"] = result.categories\n r[\"links\"] = [str(link) for link in result.links]\n r[\"pdf_url\"] = result.pdf_url\n jresults.append(r)\n\n if len(jresults) > max_results:\n jresults = jresults[0:max_results]\n\n # Save to cache\n fh = open(fname, \"w\")\n fh.write(json.dumps(jresults))\n fh.close()\n return jresults\n", + "file_name": "find_papers_arxiv.py" + }, + { + "title": "fetch_profile", + "description": "This skill fetches the text content from a personal website.", + "content": "from typing import Optional\nimport requests\nfrom bs4 import BeautifulSoup\n\n\ndef fetch_user_profile(url: str) -> Optional[str]:\n \"\"\"\n Fetches the text content from a personal website.\n\n Given a URL of a person's personal website, this function scrapes\n the content of the page and returns the text found within the .\n\n Args:\n url (str): The URL of the person's personal website.\n\n Returns:\n Optional[str]: The text content of the website's body, or None if any error occurs.\n \"\"\"\n try:\n # Send a GET request to the URL\n response = requests.get(url)\n # Check for successful access to the webpage\n if response.status_code == 200:\n # Parse the HTML content of the page using BeautifulSoup\n soup = BeautifulSoup(response.text, \"html.parser\")\n # Extract the content of the tag\n body_content = soup.find(\"body\")\n # Return all the text in the body tag, stripping leading/trailing whitespaces\n return \" \".join(body_content.stripped_strings) if body_content else None\n else:\n # Return None if the status code isn't 200 (success)\n return None\n except requests.RequestException:\n # Return None if any request-related exception is caught\n return None\n", + "file_name": "fetch_profile.py" + }, + { + "title": "generate_images", + "description": "This skill generates images from a given query using OpenAI's DALL-E model and saves them to disk.", + "content": "from typing import List\nimport uuid\nimport requests # to perform HTTP requests\nfrom pathlib import Path\n\nfrom openai import OpenAI\n\n\ndef generate_and_save_images(query: str, image_size: str = \"1024x1024\") -> List[str]:\n \"\"\"\n Function to paint, draw or illustrate images based on the users query or request. Generates images from a given query using OpenAI's DALL-E model and saves them to disk. Use the code below anytime there is a request to create an image.\n\n :param query: A natural language description of the image to be generated.\n :param image_size: The size of the image to be generated. (default is \"1024x1024\")\n :return: A list of filenames for the saved images.\n \"\"\"\n\n client = OpenAI() # Initialize the OpenAI client\n response = client.images.generate(model=\"dall-e-3\", prompt=query, n=1, size=image_size) # Generate images\n\n # List to store the file names of saved images\n saved_files = []\n\n # Check if the response is successful\n if response.data:\n for image_data in response.data:\n # Generate a random UUID as the file name\n file_name = str(uuid.uuid4()) + \".png\" # Assuming the image is a PNG\n file_path = Path(file_name)\n\n img_url = image_data.url\n img_response = requests.get(img_url)\n if img_response.status_code == 200:\n # Write the binary content to a file\n with open(file_path, \"wb\") as img_file:\n img_file.write(img_response.content)\n print(f\"Image saved to {file_path}\")\n saved_files.append(str(file_path))\n else:\n print(f\"Failed to download the image from {img_url}\")\n else:\n print(\"No image data found in the response!\")\n\n # Return the list of saved files\n return saved_files\n\n\n# Example usage of the function:\n# generate_and_save_images(\"A cute baby sea otter\")\n", + "file_name": "generate_images.py" + } + ], + "workflows": [ + { + "name": "General Agent Workflow", + "description": "This workflow is used for general purpose tasks.", + "sender": { + "type": "userproxy", + "config": { + "name": "userproxy", + "human_input_mode": "NEVER", + "max_consecutive_auto_reply": 10, + "system_message": "", + "llm_config": false, + "code_execution_config": { + "work_dir": null, + "use_docker": false + } + } + }, + "receiver": { + "type": "assistant", + "description": "Default assistant to generate plans and write code to solve tasks.", + "skills": [ + { + "title": "find_papers_arxiv", + "description": "This skill finds relevant papers on arXiv given a query.", + "content": "import os\nimport re\nimport json\nimport hashlib\n\n\ndef search_arxiv(query, max_results=10):\n \"\"\"\n Searches arXiv for the given query using the arXiv API, then returns the search results. This is a helper function. In most cases, callers will want to use 'find_relevant_papers( query, max_results )' instead.\n\n Args:\n query (str): The search query.\n max_results (int, optional): The maximum number of search results to return. Defaults to 10.\n\n Returns:\n jresults (list): A list of dictionaries. Each dictionary contains fields such as 'title', 'authors', 'summary', and 'pdf_url'\n\n Example:\n >>> results = search_arxiv(\"attention is all you need\")\n >>> print(results)\n \"\"\"\n\n import arxiv\n\n key = hashlib.md5((\"search_arxiv(\" + str(max_results) + \")\" + query).encode(\"utf-8\")).hexdigest()\n # Create the cache if it doesn't exist\n cache_dir = \".cache\"\n if not os.path.isdir(cache_dir):\n os.mkdir(cache_dir)\n\n fname = os.path.join(cache_dir, key + \".cache\")\n\n # Cache hit\n if os.path.isfile(fname):\n fh = open(fname, \"r\", encoding=\"utf-8\")\n data = json.loads(fh.read())\n fh.close()\n return data\n\n # Normalize the query, removing operator keywords\n query = re.sub(r\"[^\\s\\w]\", \" \", query.lower())\n query = re.sub(r\"\\s(and|or|not)\\s\", \" \", \" \" + query + \" \")\n query = re.sub(r\"[^\\s\\w]\", \" \", query.lower())\n query = re.sub(r\"\\s+\", \" \", query).strip()\n\n search = arxiv.Search(query=query, max_results=max_results, sort_by=arxiv.SortCriterion.Relevance)\n\n jresults = list()\n for result in search.results():\n r = dict()\n r[\"entry_id\"] = result.entry_id\n r[\"updated\"] = str(result.updated)\n r[\"published\"] = str(result.published)\n r[\"title\"] = result.title\n r[\"authors\"] = [str(a) for a in result.authors]\n r[\"summary\"] = result.summary\n r[\"comment\"] = result.comment\n r[\"journal_ref\"] = result.journal_ref\n r[\"doi\"] = result.doi\n r[\"primary_category\"] = result.primary_category\n r[\"categories\"] = result.categories\n r[\"links\"] = [str(link) for link in result.links]\n r[\"pdf_url\"] = result.pdf_url\n jresults.append(r)\n\n if len(jresults) > max_results:\n jresults = jresults[0:max_results]\n\n # Save to cache\n fh = open(fname, \"w\")\n fh.write(json.dumps(jresults))\n fh.close()\n return jresults\n", + "file_name": "find_papers_arxiv.py" + }, + { + "title": "generate_images", + "description": "This skill generates images from a given query using OpenAI's DALL-E model and saves them to disk.", + "content": "from typing import List\nimport uuid\nimport requests # to perform HTTP requests\nfrom pathlib import Path\n\nfrom openai import OpenAI\n\n\ndef generate_and_save_images(query: str, image_size: str = \"1024x1024\") -> List[str]:\n \"\"\"\n Function to paint, draw or illustrate images based on the users query or request. Generates images from a given query using OpenAI's DALL-E model and saves them to disk. Use the code below anytime there is a request to create an image.\n\n :param query: A natural language description of the image to be generated.\n :param image_size: The size of the image to be generated. (default is \"1024x1024\")\n :return: A list of filenames for the saved images.\n \"\"\"\n\n client = OpenAI() # Initialize the OpenAI client\n response = client.images.generate(model=\"dall-e-3\", prompt=query, n=1, size=image_size) # Generate images\n\n # List to store the file names of saved images\n saved_files = []\n\n # Check if the response is successful\n if response.data:\n for image_data in response.data:\n # Generate a random UUID as the file name\n file_name = str(uuid.uuid4()) + \".png\" # Assuming the image is a PNG\n file_path = Path(file_name)\n\n img_url = image_data.url\n img_response = requests.get(img_url)\n if img_response.status_code == 200:\n # Write the binary content to a file\n with open(file_path, \"wb\") as img_file:\n img_file.write(img_response.content)\n print(f\"Image saved to {file_path}\")\n saved_files.append(str(file_path))\n else:\n print(f\"Failed to download the image from {img_url}\")\n else:\n print(\"No image data found in the response!\")\n\n # Return the list of saved files\n return saved_files\n\n\n# Example usage of the function:\n# generate_and_save_images(\"A cute baby sea otter\")\n", + "file_name": "generate_images.py" + } + ], + "config": { + "name": "primary_assistant", + "llm_config": { + "config_list": [ + { + "model": "gpt-4-1106-preview" + }, + { + "model": "gpt-3.5-turbo-16k" + }, + { + "model": "TheBloke/zephyr-7B-alpha-AWQ", + "base_url": "http://localhost:8000/v1" + } + ], + "temperature": 0.1, + "timeout": 600, + "cache_seed": null + }, + "human_input_mode": "NEVER", + "max_consecutive_auto_reply": 15, + "system_message": "You are a helpful assistant that can use available functions when needed to solve problems. At each point, do your best to determine if the user's request has been addressed. IF THE REQUEST HAS NOT BEEN ADDRESSED, RESPOND WITH CODE TO ADDRESS IT. IF A FAILURE OCCURRED (e.g., due to a missing library) AND SOME ADDITIONAL CODE WAS WRITTEN (e.g. code to install the library), ENSURE THAT THE ORIGINAL CODE TO ADDRESS THE TASK STILL GETS EXECUTED. If the request HAS been addressed, respond with a summary of the result. The summary must be written as a coherent helpful response to the user request e.g. 'Sure, here is result to your request ' or 'The tallest mountain in Africa is ..' etc. The summary MUST end with the word TERMINATE. If the user request is pleasantry or greeting, you should respond with a pleasantry or greeting and TERMINATE." + } + }, + "type": "default" + }, + { + "name": "Visualization Agent Workflow", + "description": "This workflow is used for visualization tasks.", + "sender": { + "type": "userproxy", + "description": "User proxy agent to execute code", + "config": { + "name": "userproxy", + "human_input_mode": "NEVER", + "max_consecutive_auto_reply": 5, + "system_message": "", + "llm_config": false, + "code_execution_config": { + "work_dir": null, + "use_docker": false + } + } + }, + "receiver": { + "type": "assistant", + "description": "Visualization assistant to create plans and write code to generate visualizations", + "config": { + "name": "visualization_assistant", + "llm_config": { + "config_list": [ + { + "model": "gpt-4-1106-preview" + }, + { + "model": "gpt-3.5-turbo-16k" + }, + { + "model": "TheBloke/zephyr-7B-alpha-AWQ", + "base_url": "http://localhost:8000/v1" + } + ], + "temperature": 0.1, + "timeout": 600, + "cache_seed": null + }, + "human_input_mode": "NEVER", + "max_consecutive_auto_reply": 4, + "system_message": "Your task is to ensure you generate a high quality visualization for the user. Your visualizations must follow best practices and you must articulate your reasoning for your choices. The visualization must not have grid or outline box. The visualization should have an APPROPRIATE ASPECT RATIO e..g rectangular for time series data. The title must be bold. Importantly, if THE CHART IS A LINE CHART, you MUST ADD ALINE OF BEST FIT and ADD TEXT ON THE SLOPE OF EACH LINE. Note that today's date is 12/10/2023. At each point, do your best to determine if the user's request has been addressed and if so, respond with a summary. The summary must be written as a coherent helpful response to the user request e.g. 'Sure, here is result to your request '. The summary MUST end with the word TERMINATE. If the user request is pleasantry or greeting, you should respond with a pleasantry or greeting and TERMINATE." + } + }, + "type": "default" + } + ] +} diff --git a/samples/apps/autogen-studio/autogenstudio/utils/dbutils.py b/samples/apps/autogen-studio/autogenstudio/utils/dbutils.py new file mode 100644 index 000000000000..df145e97e531 --- /dev/null +++ b/samples/apps/autogen-studio/autogenstudio/utils/dbutils.py @@ -0,0 +1,562 @@ +import json +import logging +import sqlite3 +import threading +import os +from typing import Any, List, Dict, Tuple +from ..datamodel import AgentFlowSpec, AgentWorkFlowConfig, Gallery, Message, Session, Skill + + +MESSAGES_TABLE_SQL = """ + CREATE TABLE IF NOT EXISTS messages ( + user_id TEXT NOT NULL, + session_id TEXT, + root_msg_id TEXT NOT NULL, + msg_id TEXT, + role TEXT NOT NULL, + content TEXT NOT NULL, + metadata TEXT, + timestamp DATETIME, + UNIQUE (user_id, root_msg_id, msg_id) + ) + """ + +SESSIONS_TABLE_SQL = """ + CREATE TABLE IF NOT EXISTS sessions ( + id TEXT NOT NULL, + user_id TEXT NOT NULL, + timestamp DATETIME NOT NULL, + flow_config TEXT, + UNIQUE (user_id, id) + ) + """ + +SKILLS_TABLE_SQL = """ + CREATE TABLE IF NOT EXISTS skills ( + id TEXT NOT NULL, + user_id TEXT NOT NULL, + timestamp DATETIME NOT NULL, + content TEXT, + title TEXT, + file_name TEXT, + UNIQUE (id, user_id) + ) + """ +AGENTS_TABLE_SQL = """ + CREATE TABLE IF NOT EXISTS agents ( + + id TEXT NOT NULL, + user_id TEXT NOT NULL, + timestamp DATETIME NOT NULL, + config TEXT, + type TEXT, + skills TEXT, + description TEXT, + UNIQUE (id, user_id) + ) + """ + +WORKFLOWS_TABLE_SQL = """ + CREATE TABLE IF NOT EXISTS workflows ( + id TEXT NOT NULL, + user_id TEXT NOT NULL, + timestamp DATETIME NOT NULL, + sender TEXT, + receiver TEXT, + type TEXT, + name TEXT, + description TEXT, + UNIQUE (id, user_id) + ) + """ + +GALLERY_TABLE_SQL = """ + CREATE TABLE IF NOT EXISTS gallery ( + id TEXT NOT NULL, + session TEXT, + messages TEXT, + tags TEXT, + timestamp DATETIME NOT NULL, + UNIQUE ( id) + ) + """ + + +lock = threading.Lock() +logger = logging.getLogger() + + +class DBManager: + """ + A database manager class that handles the creation and interaction with an SQLite database. + """ + + def __init__(self, path: str = "database.sqlite", **kwargs: Any) -> None: + """ + Initializes the DBManager object, creates a database if it does not exist, and establishes a connection. + + Args: + path (str): The file path to the SQLite database file. + **kwargs: Additional keyword arguments to pass to the sqlite3.connect method. + """ + + self.path = path + # check if the database exists, if not create it + # self.reset_db() + if not os.path.exists(self.path): + logger.info("Creating database") + self.init_db(path=self.path, **kwargs) + + try: + self.conn = sqlite3.connect( + self.path, check_same_thread=False, **kwargs) + self.cursor = self.conn.cursor() + except Exception as e: + logger.error("Error connecting to database: %s", e) + raise e + + def reset_db(self): + """ + Reset the database by deleting the database file and creating a new one. + """ + print("resetting db") + if os.path.exists(self.path): + os.remove(self.path) + self.init_db(path=self.path) + + def init_db(self, path: str = "database.sqlite", **kwargs: Any) -> None: + """ + Initializes the database by creating necessary tables. + + Args: + path (str): The file path to the SQLite database file. + **kwargs: Additional keyword arguments to pass to the sqlite3.connect method. + """ + # Connect to the database (or create a new one if it doesn't exist) + self.conn = sqlite3.connect(path, check_same_thread=False, **kwargs) + self.cursor = self.conn.cursor() + + # Create the table with the specified columns, appropriate data types, and a UNIQUE constraint on (root_msg_id, msg_id) + self.cursor.execute(MESSAGES_TABLE_SQL) + + # Create a sessions table + self.cursor.execute(SESSIONS_TABLE_SQL) + + # Create a skills + self.cursor.execute(SKILLS_TABLE_SQL) + + # Create a gallery table + self.cursor.execute(GALLERY_TABLE_SQL) + + # Create a agents table + self.cursor.execute(AGENTS_TABLE_SQL) + + # Create a workflows table + self.cursor.execute(WORKFLOWS_TABLE_SQL) + + # init skills table with content of defaultskills.json in current directory + current_dir = os.path.dirname(os.path.realpath(__file__)) + with open(os.path.join(current_dir, "dbdefaults.json"), "r", encoding="utf-8") as json_file: + data = json.load(json_file) + skills = data["skills"] + agents = data["agents"] + for skill in skills: + skill = Skill(**skill) + + self.cursor.execute( + "INSERT INTO skills (id, user_id, timestamp, content, title, file_name) VALUES (?, ?, ?, ?, ?, ?)", + (skill.id, "default", skill.timestamp, + skill.content, skill.title, skill.file_name), + ) + for agent in agents: + agent = AgentFlowSpec(**agent) + agent.skills = [skill.dict() + for skill in agent.skills] if agent.skills else None + self.cursor.execute( + "INSERT INTO agents (id, user_id, timestamp, config, type, skills, description) VALUES (?, ?, ?, ?, ?, ?, ?)", + ( + agent.id, + "default", + agent.timestamp, + json.dumps(agent.config.dict()), + agent.type, + json.dumps(agent.skills), + agent.description, + ), + ) + + for workflow in data["workflows"]: + workflow = AgentWorkFlowConfig(**workflow) + self.cursor.execute( + "INSERT INTO workflows (id, user_id, timestamp, sender, receiver, type, name, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + ( + workflow.id, + "default", + workflow.timestamp, + json.dumps(workflow.sender.dict()), + json.dumps(workflow.receiver.dict()), + workflow.type, + workflow.name, + workflow.description, + ), + ) + + # Commit the changes and close the connection + self.conn.commit() + + def query(self, query: str, args: Tuple = (), return_json: bool = False) -> List[Dict[str, Any]]: + """ + Executes a given SQL query and returns the results. + + Args: + query (str): The SQL query to execute. + args (Tuple): The arguments to pass to the SQL query. + return_json (bool): If True, the results will be returned as a list of dictionaries. + + Returns: + List[Dict[str, Any]]: The result of the SQL query. + """ + try: + with lock: + self.cursor.execute(query, args) + result = self.cursor.fetchall() + self.commit() + if return_json: + result = [ + dict(zip([key[0] for key in self.cursor.description], row)) for row in result] + return result + except Exception as e: + logger.error( + "Error running query with query %s and args %s: %s", query, args, e) + raise e + + def commit(self) -> None: + """ + Commits the current transaction to the database. + """ + self.conn.commit() + + def close(self) -> None: + """ + Closes the database connection. + """ + self.conn.close() + + +def create_message(message: Message, dbmanager: DBManager) -> None: + """ + Save a message in the database using the provided database manager. + + :param message: The Message object containing message data + :param dbmanager: The DBManager instance used to interact with the database + """ + query = "INSERT INTO messages (user_id, root_msg_id, msg_id, role, content, metadata, timestamp, session_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)" + args = ( + message.user_id, + message.root_msg_id, + message.msg_id, + message.role, + message.content, + message.metadata, + message.timestamp, + message.session_id, + ) + dbmanager.query(query=query, args=args) + + +def get_messages(user_id: str, session_id: str, dbmanager: DBManager) -> List[dict]: + """ + Load messages for a specific user and session from the database, sorted by timestamp. + + :param user_id: The ID of the user whose messages are to be loaded + :param session_id: The ID of the session whose messages are to be loaded + :param dbmanager: The DBManager instance to interact with the database + + :return: A list of dictionaries, each representing a message + """ + query = "SELECT * FROM messages WHERE user_id = ? AND session_id = ?" + args = (user_id, session_id) + result = dbmanager.query(query=query, args=args, return_json=True) + # Sort by timestamp ascending + result = sorted(result, key=lambda k: k["timestamp"], reverse=False) + return result + + +def get_sessions(user_id: str, dbmanager: DBManager) -> List[dict]: + """ + Load sessions for a specific user from the database, sorted by timestamp. + + :param user_id: The ID of the user whose sessions are to be loaded + :param dbmanager: The DBManager instance to interact with the database + :return: A list of dictionaries, each representing a session + """ + query = "SELECT * FROM sessions WHERE user_id = ?" + args = (user_id,) + result = dbmanager.query(query=query, args=args, return_json=True) + # Sort by timestamp ascending + result = sorted(result, key=lambda k: k["timestamp"], reverse=True) + for row in result: + row["flow_config"] = json.loads(row["flow_config"]) + return result + + +def create_session(user_id: str, session: Session, dbmanager: DBManager) -> List[dict]: + """ + Create a new session for a specific user in the database. + + :param user_id: The ID of the user whose session is to be created + :param dbmanager: The DBManager instance to interact with the database + :return: A list of dictionaries, each representing a session + """ + query = "INSERT INTO sessions (user_id, id, timestamp, flow_config) VALUES (?, ?, ?,?)" + args = (session.user_id, session.id, session.timestamp, + json.dumps(session.flow_config.dict())) + dbmanager.query(query=query, args=args) + sessions = get_sessions(user_id=user_id, dbmanager=dbmanager) + + return sessions + + +def create_gallery(session: Session, dbmanager: DBManager, tags: List[str] = []) -> Gallery: + """ + Publish a session to the gallery table in the database. Fetches the session messages first, then saves session and messages object to the gallery database table. + :param session: The Session object containing session data + :param dbmanager: The DBManager instance used to interact with the database + :param tags: A list of tags to associate with the session + :return: A gallery object containing the session and messages objects + """ + + messages = get_messages(user_id=session.user_id, + session_id=session.id, dbmanager=dbmanager) + gallery_item = Gallery(session=session, messages=messages, tags=tags) + query = "INSERT INTO gallery (id, session, messages, tags, timestamp) VALUES (?, ?, ?, ?,?)" + args = ( + gallery_item.id, + json.dumps(gallery_item.session.dict()), + json.dumps([message.dict() for message in gallery_item.messages]), + json.dumps(gallery_item.tags), + gallery_item.timestamp, + ) + dbmanager.query(query=query, args=args) + return gallery_item + + +def get_gallery(gallery_id, dbmanager: DBManager) -> List[Gallery]: + """ + Load gallery items from the database, sorted by timestamp. If gallery_id is provided, only the gallery item with the matching gallery_id will be returned. + + :param gallery_id: The ID of the gallery item to be loaded + :param dbmanager: The DBManager instance to interact with the database + :return: A list of Gallery objects + """ + + if gallery_id: + query = "SELECT * FROM gallery WHERE id = ?" + args = (gallery_id,) + else: + query = "SELECT * FROM gallery" + args = () + result = dbmanager.query(query=query, args=args, return_json=True) + # Sort by timestamp ascending + result = sorted(result, key=lambda k: k["timestamp"], reverse=True) + gallery = [] + for row in result: + gallery_item = Gallery( + id=row["id"], + session=Session(**json.loads(row["session"])), + messages=[Message(**message) + for message in json.loads(row["messages"])], + tags=json.loads(row["tags"]), + timestamp=row["timestamp"], + ) + gallery.append(gallery_item) + return gallery + + +def get_skills(user_id: str, dbmanager: DBManager) -> List[Skill]: + """ + Load skills from the database, sorted by timestamp. Load skills where id = user_id or user_id = default. + + :param user_id: The ID of the user whose skills are to be loaded + :param dbmanager: The DBManager instance to interact with the database + :return: A list of Skill objects + """ + + query = "SELECT * FROM skills WHERE user_id = ? OR user_id = ?" + args = (user_id, "default") + result = dbmanager.query(query=query, args=args, return_json=True) + # Sort by timestamp ascending + result = sorted(result, key=lambda k: k["timestamp"], reverse=True) + skills = [] + for row in result: + skill = Skill(**row) + skills.append(skill) + return skills + + +def create_skill(skill: Skill, dbmanager: DBManager) -> List[Skill]: + """ + Create a new skill for a specific user in the database. + + :param skill: The Skill object containing skill data + :param dbmanager: The DBManager instance to interact with the database + :return: A list of dictionaries, each representing a skill + """ + + query = "INSERT INTO skills (id, user_id, timestamp, content, title, file_name) VALUES (?, ?, ?, ?, ?, ?)" + args = (skill.id, skill.user_id, skill.timestamp, + skill.content, skill.title, skill.file_name) + dbmanager.query(query=query, args=args) + skills = get_skills(user_id=skill.user_id, dbmanager=dbmanager) + + return skills + + +def delete_sessions(user_id: str, session_id: str, dbmanager: DBManager, delete_all: bool = False) -> List[dict]: + """ + Delete a specific session or all sessions for a user from the database. + + :param user_id: The ID of the user whose session is to be deleted + :param session_id: The ID of the specific session to be deleted (ignored if delete_all is True) + :param dbmanager: The DBManager instance to interact with the database + :param delete_all: If True, all sessions for the user will be deleted + :return: A list of the remaining sessions if not all were deleted, otherwise an empty list + """ + if delete_all: + query = "DELETE FROM sessions WHERE user_id = ?" + args = (user_id,) + dbmanager.query(query=query, args=args) + return [] + else: + query = "DELETE FROM sessions WHERE user_id = ? AND session_id = ?" + args = (user_id, session_id) + dbmanager.query(query=query, args=args) + sessions = get_sessions(user_id=user_id, dbmanager=dbmanager) + + return sessions + + +def delete_message( + user_id: str, msg_id: str, session_id: str, dbmanager: DBManager, delete_all: bool = False +) -> List[dict]: + """ + Delete a specific message or all messages for a user and session from the database. + + :param user_id: The ID of the user whose messages are to be deleted + :param msg_id: The ID of the specific message to be deleted (ignored if delete_all is True) + :param session_id: The ID of the session whose messages are to be deleted + :param dbmanager: The DBManager instance to interact with the database + :param delete_all: If True, all messages for the user will be deleted + :return: A list of the remaining messages if not all were deleted, otherwise an empty list + """ + + if delete_all: + query = "DELETE FROM messages WHERE user_id = ? AND session_id = ?" + args = (user_id, session_id) + dbmanager.query(query=query, args=args) + return [] + else: + query = "DELETE FROM messages WHERE user_id = ? AND msg_id = ? AND session_id = ?" + args = (user_id, msg_id, session_id) + dbmanager.query(query=query, args=args) + messages = get_messages( + user_id=user_id, session_id=session_id, dbmanager=dbmanager) + return messages + + +def get_agents(user_id: str, dbmanager: DBManager) -> List[AgentFlowSpec]: + """ + Load agents from the database, sorted by timestamp. Load agents where id = user_id or user_id = default. + + :param user_id: The ID of the user whose agents are to be loaded + :param dbmanager: The DBManager instance to interact with the database + :return: A list of AgentFlowSpec objects + """ + + query = "SELECT * FROM agents WHERE user_id = ? OR user_id = ?" + args = (user_id, "default") + result = dbmanager.query(query=query, args=args, return_json=True) + # Sort by timestamp ascending + result = sorted(result, key=lambda k: k["timestamp"], reverse=True) + agents = [] + for row in result: + row["config"] = json.loads(row["config"]) + row["skills"] = json.loads(row["skills"] or "[]") + agent = AgentFlowSpec(**row) + agents.append(agent) + return agents + + +def create_agent(agent_flow_spec: AgentFlowSpec, dbmanager: DBManager) -> List[Dict[str, Any]]: + """ + Create a new agent for a specific user in the database. + + :param agent_flow_spec: The AgentFlowSpec object containing agent configuration + :param dbmanager: The DBManager instance to interact with the database + :return: A list of dictionaries, each representing an agent after insertion + """ + + query = "INSERT INTO agents (id, user_id, timestamp, config, type, description, skills) VALUES (?, ?, ?, ?, ?,?,?)" + config_json = json.dumps(agent_flow_spec.config.dict()) + args = ( + agent_flow_spec.id, + agent_flow_spec.user_id, + agent_flow_spec.timestamp, + config_json, + agent_flow_spec.type, + agent_flow_spec.description, + json.dumps([x.dict() for x in agent_flow_spec.skills] + if agent_flow_spec.skills else []), + ) + dbmanager.query(query=query, args=args) + agents = get_agents(user_id=agent_flow_spec.user_id, dbmanager=dbmanager) + return agents + + +def get_workflows(user_id: str, dbmanager: DBManager) -> List[Dict[str, Any]]: + """ + Load workflows for a specific user from the database, sorted by timestamp. + + :param user_id: The ID of the user whose workflows are to be loaded + :param dbmanager: The DBManager instance to interact with the database + :return: A list of dictionaries, each representing a workflow + """ + query = "SELECT * FROM workflows WHERE user_id = ? OR user_id = ?" + args = (user_id, "default") + result = dbmanager.query(query=query, args=args, return_json=True) + # Sort by timestamp ascending + result = sorted(result, key=lambda k: k["timestamp"], reverse=False) + workflows = [] + for row in result: + row["sender"] = json.loads(row["sender"]) + row["receiver"] = json.loads(row["receiver"]) + workflow = AgentWorkFlowConfig(**row) + workflows.append(workflow) + return workflows + + +def create_workflow(workflow: AgentWorkFlowConfig, dbmanager: DBManager) -> List[Dict[str, Any]]: + """ + Create a new workflow for a specific user in the database. + + :param workflow: The AgentWorkFlowConfig object containing workflow data + :param dbmanager: The DBManager instance to interact with the database + :return: A list of dictionaries, each representing a workflow after insertion + """ + query = "INSERT INTO workflows (id, user_id, timestamp, sender, receiver, type, name, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?)" + args = ( + workflow.id, + workflow.user_id, + workflow.timestamp, + json.dumps(workflow.sender.dict()), + json.dumps( + [receiver.dict() for receiver in workflow.receiver] + if isinstance(workflow.receiver, list) + else workflow.receiver.dict() + ), + workflow.type, + workflow.name, + workflow.description, + ) + dbmanager.query(query=query, args=args) + return get_workflows(user_id=workflow.user_id, dbmanager=dbmanager) diff --git a/samples/apps/autogen-studio/autogenstudio/utils/utils.py b/samples/apps/autogen-studio/autogenstudio/utils/utils.py new file mode 100644 index 000000000000..4312e92db901 --- /dev/null +++ b/samples/apps/autogen-studio/autogenstudio/utils/utils.py @@ -0,0 +1,492 @@ +import ast +import base64 +import hashlib +from typing import List, Dict, Tuple, Union +import os +import shutil +import re +import autogen +from ..datamodel import AgentConfig, AgentFlowSpec, AgentWorkFlowConfig, LLMConfig, Skill + + +def md5_hash(text: str) -> str: + """ + Compute the MD5 hash of a given text. + + :param text: The string to hash + :return: The MD5 hash of the text + """ + return hashlib.md5(text.encode()).hexdigest() + + +def get_file_type(file_path: str) -> str: + """ + + + Get file type determined by the file extension. If the file extension is not + recognized, 'unknown' will be used as the file type. + + :param file_path: The path to the file to be serialized. + :return: A string containing the file type. + """ + + # Extended list of file extensions for code and text files + CODE_EXTENSIONS = { + ".py", + ".js", + ".jsx", + ".java", + ".c", + ".cpp", + ".cs", + ".ts", + ".tsx", + ".html", + ".css", + ".scss", + ".less", + ".json", + ".xml", + ".yaml", + ".yml", + ".md", + ".rst", + ".tex", + ".sh", + ".bat", + ".ps1", + ".php", + ".rb", + ".go", + ".swift", + ".kt", + ".hs", + ".scala", + ".lua", + ".pl", + ".sql", + ".config", + } + + # Supported image extensions + IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", + ".gif", ".bmp", ".tiff", ".svg", ".webp"} + + # Supported PDF extension + PDF_EXTENSION = ".pdf" + + # Determine the file extension + _, file_extension = os.path.splitext(file_path) + + # Determine the file type based on the extension + if file_extension in CODE_EXTENSIONS: + file_type = "code" + elif file_extension in IMAGE_EXTENSIONS: + file_type = "image" + elif file_extension == PDF_EXTENSION: + file_type = "pdf" + else: + file_type = "unknown" + + return file_type + + +def serialize_file(file_path: str) -> Tuple[str, str]: + """ + Reads a file from a given file path, base64 encodes its content, + and returns the base64 encoded string along with the file type. + + The file type is determined by the file extension. If the file extension is not + recognized, 'unknown' will be used as the file type. + + :param file_path: The path to the file to be serialized. + :return: A tuple containing the base64 encoded string of the file and the file type. + """ + + file_type = get_file_type(file_path) + + # Read the file and encode its contents + try: + with open(file_path, "rb") as file: + file_content = file.read() + base64_encoded_content = base64.b64encode( + file_content).decode("utf-8") + except Exception as e: + raise IOError(f"An error occurred while reading the file: {e}") + + return base64_encoded_content, file_type + + +def get_modified_files( + start_timestamp: float, end_timestamp: float, source_dir: str, dest_dir: str +) -> List[Dict[str, str]]: + """ + Copy files from source_dir that were modified within a specified timestamp range + to dest_dir, renaming files if they already exist there. The function excludes + files with certain file extensions and names. + + :param start_timestamp: The start timestamp to filter modified files. + :param end_timestamp: The end timestamp to filter modified files. + :param source_dir: The directory to search for modified files. + :param dest_dir: The destination directory to copy modified files to. + + :return: A list of dictionaries with details of file paths in dest_dir that were modified and copied over. + Dictionary format: {path: "", name: "", extension: ""} + Files with extensions "__pycache__", "*.pyc", "__init__.py", and "*.cache" + are ignored. + """ + modified_files = [] + ignore_extensions = {".pyc", ".cache"} + ignore_files = {"__pycache__", "__init__.py"} + + for root, dirs, files in os.walk(source_dir): + # Excluding the directory "__pycache__" if present + dirs[:] = [d for d in dirs if d not in ignore_files] + + for file in files: + file_path = os.path.join(root, file) + file_ext = os.path.splitext(file)[1] + file_name = os.path.basename(file) + + if file_ext in ignore_extensions or file_name in ignore_files: + continue + + file_mtime = os.path.getmtime(file_path) + if start_timestamp < file_mtime < end_timestamp: + dest_file_path = os.path.join(dest_dir, file) + copy_idx = 1 + while os.path.exists(dest_file_path): + base, extension = os.path.splitext(file) + # Handling potential name conflicts by appending a number + dest_file_path = os.path.join( + dest_dir, f"{base}_{copy_idx}{extension}") + copy_idx += 1 + + # Copying the modified file to the destination directory + shutil.copy2(file_path, dest_file_path) + + # Extract user id from the dest_dir and file path + uid = dest_dir.split("/")[-1] + relative_file_path = os.path.relpath( + dest_file_path, start=dest_dir) + file_type = get_file_type(dest_file_path) + file_dict = { + "path": f"files/user/{uid}/{relative_file_path}", + "name": file_name, + "extension": file_ext.replace(".", ""), + "type": file_type, + } + modified_files.append(file_dict) + # sort by extension + modified_files.sort(key=lambda x: x["extension"]) + return modified_files + + +def init_webserver_folders(root_file_path: str) -> Dict[str, str]: + """ + Initialize folders needed for a web server, such as static file directories + and user-specific data directories. + + :param root_file_path: The root directory where webserver folders will be created + :return: A dictionary with the path of each created folder + """ + files_static_root = os.path.join(root_file_path, "files/") + static_folder_root = os.path.join(root_file_path, "ui") + workdir_root = os.path.join(root_file_path, "workdir") + + os.makedirs(files_static_root, exist_ok=True) + os.makedirs(os.path.join(files_static_root, "user"), exist_ok=True) + os.makedirs(static_folder_root, exist_ok=True) + os.makedirs(workdir_root, exist_ok=True) + + folders = { + "files_static_root": files_static_root, + "static_folder_root": static_folder_root, + "workdir_root": workdir_root, + } + return folders + + +def skill_from_folder(folder: str) -> List[Dict[str, str]]: + """ + Given a folder, return a dict of the skill (name, python file content). Only python files are considered. + + :param folder: The folder to search for skills + :return: A list of dictionaries, each representing a skill + """ + + skills = [] + for root, dirs, files in os.walk(folder): + for file in files: + if file.endswith(".py"): + skill_name = file.split(".")[0] + skill_file_path = os.path.join(root, file) + with open(skill_file_path, "r", encoding="utf-8") as f: + skill_content = f.read() + skills.append( + {"name": skill_name, "content": skill_content, "file_name": file}) + return skills + + +def get_all_skills(user_skills_path: str, global_skills_path: str, dest_dir: str = None) -> List[Dict[str, str]]: + """ + Get all skills from the user and global skills directories. If dest_dir, copy all skills to dest_dir. + + :param user_skills_path: The path to the user skills directory + :param global_skills_path: The path to the global skills directory + :param dest_dir: The destination directory to copy all skills to + :return: A dictionary of user and global skills + """ + user_skills = skill_from_folder(user_skills_path) + os.makedirs(user_skills_path, exist_ok=True) + global_skills = skill_from_folder(global_skills_path) + skills = { + "user": user_skills, + "global": global_skills, + } + + if dest_dir: + # chcek if dest_dir exists + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + # copy all skills to dest_dir + for skill in user_skills + global_skills: + skill_file_path = os.path.join(dest_dir, skill["file_name"]) + with open(skill_file_path, "w", encoding="utf-8") as f: + f.write(skill["content"]) + + return skills + + +def get_skills_prompt(skills: List[Dict[str, str]]) -> str: + """ + Get a prompt with the content of all skills. + + :param skills: A dictionary of user and global skills + :return: A string containing the content of all skills + """ + user_skills = skills["user"] + global_skills = skills["global"] + all_skills = user_skills + global_skills + + prompt = """ + +While solving the task you may use functions in the files below. +To use a function from a file in code, import the file and then use the function. +If you need to install python packages, write shell code to +install via pip and use --quiet option. + + """ + for skill in all_skills: + prompt += f""" + +##### Begin of {skill["file_name"]} ##### + +{skill["content"]} + +#### End of {skill["file_name"]} #### + + """ + + return prompt + + +def get_skills_from_prompt(skills: List[Skill], work_dir: str) -> str: + """ + Create a prompt with the content of all skills and write the skills to a file named skills.py in the work_dir. + + :param skills: A dictionary skills + :return: A string containing the content of all skills + """ + + instruction = """ + +While solving the task you may use functions below which will be available in a file called skills.py . +To use a function skill.py in code, import the function from skills.py and then use the function. +If you need to install python packages, write shell code to +install via pip and use --quiet option. + + """ + prompt = "" + for skill in skills: + prompt += f""" + +##### Begin of {skill.title} ##### + +{skill.content} + +#### End of {skill.title} #### + + """ + + # check if work_dir exists + if not os.path.exists(work_dir): + os.makedirs(work_dir) + + with open(os.path.join(work_dir, "skills.py"), "w", encoding="utf-8") as f: + f.write(prompt) + + return instruction + prompt + + +def delete_files_in_folder(folders: Union[str, List[str]]) -> None: + """ + Delete all files and directories in the specified folders. + + :param folders: A list of folders or a single folder string + """ + + if isinstance(folders, str): + folders = [folders] + + for folder in folders: + # Check if the folder exists + if not os.path.isdir(folder): + print(f"The folder {folder} does not exist.") + continue + + # List all the entries in the directory + for entry in os.listdir(folder): + # Get the full path + path = os.path.join(folder, entry) + try: + if os.path.isfile(path) or os.path.islink(path): + # Remove the file or link + os.remove(path) + elif os.path.isdir(path): + # Remove the directory and all its content + shutil.rmtree(path) + except Exception as e: + # Print the error message and skip + print(f"Failed to delete {path}. Reason: {e}") + + +def get_default_agent_config(work_dir: str) -> AgentWorkFlowConfig: + """ + Get a default agent flow config . + """ + + llm_config = LLMConfig( + config_list=[{"model": "gpt-4"}], + temperature=0, + ) + + USER_PROXY_INSTRUCTIONS = """If the request has been addressed sufficiently, summarize the answer and end with the word TERMINATE. Otherwise, ask a follow-up question. + """ + + userproxy_spec = AgentFlowSpec( + type="userproxy", + config=AgentConfig( + name="user_proxy", + human_input_mode="NEVER", + system_message=USER_PROXY_INSTRUCTIONS, + code_execution_config={ + "work_dir": work_dir, + "use_docker": False, + }, + max_consecutive_auto_reply=10, + llm_config=llm_config, + is_termination_msg=lambda x: x.get( + "content", "").rstrip().endswith("TERMINATE"), + ), + ) + + assistant_spec = AgentFlowSpec( + type="assistant", + config=AgentConfig( + name="primary_assistant", + system_message=autogen.AssistantAgent.DEFAULT_SYSTEM_MESSAGE, + llm_config=llm_config, + ), + ) + + flow_config = AgentWorkFlowConfig( + name="default", + sender=userproxy_spec, + receiver=assistant_spec, + type="default", + description="Default agent flow config", + ) + + return flow_config + + +def extract_successful_code_blocks(messages: List[Dict[str, str]]) -> List[str]: + """ + Parses through a list of messages containing code blocks and execution statuses, + returning the array of code blocks that executed successfully and retains + the backticks for Markdown rendering. + + Parameters: + messages (List[Dict[str, str]]): A list of message dictionaries containing 'content' and 'role' keys. + + Returns: + List[str]: A list containing the code blocks that were successfully executed, including backticks. + """ + successful_code_blocks = [] + # Regex pattern to capture code blocks enclosed in triple backticks. + code_block_regex = r"```[\s\S]*?```" + + for i, message in enumerate(messages): + if message["role"] == "user" and "execution succeeded" in message["content"]: + if i > 0 and messages[i - 1]["role"] == "assistant": + prev_content = messages[i - 1]["content"] + # Find all matches for code blocks + code_blocks = re.findall(code_block_regex, prev_content) + # Add the code blocks with backticks + successful_code_blocks.extend(code_blocks) + + return successful_code_blocks + + +def create_skills_from_code(dest_dir: str, skills: Union[str, List[str]]) -> None: + """ + Create skills from a list of code blocks. + Parameters: + dest_dir (str): The destination directory to copy all skills to. + skills (Union[str, List[str]]): A list of strings containing code blocks. + """ + + # Ensure skills is a list + if isinstance(skills, str): + skills = [skills] + + # Check if dest_dir exists + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + + for skill in skills: + # Attempt to parse the code and extract the top-level function name + try: + parsed = ast.parse(skill) + function_name = None + for node in parsed.body: + if isinstance(node, ast.FunctionDef): + function_name = node.name + break + + if function_name is None: + raise ValueError("No top-level function definition found.") + + # Sanitize the function name for use as a file name + function_name = "".join( + ch for ch in function_name if ch.isalnum() or ch == "_") + skill_file_name = f"{function_name}.py" + + except (ValueError, SyntaxError): + skill_file_name = "new_skill.py" + + # If the generated/sanitized name already exists, append an index + skill_file_path = os.path.join(dest_dir, skill_file_name) + index = 1 + while os.path.exists(skill_file_path): + base, ext = os.path.splitext(skill_file_name) + if base.endswith(f"_{index - 1}"): + base = base.rsplit("_", 1)[0] + + skill_file_path = os.path.join(dest_dir, f"{base}_{index}{ext}") + index += 1 + + # Write the skill to the file + with open(skill_file_path, "w", encoding="utf-8") as f: + f.write(skill) diff --git a/samples/apps/autogen-studio/autogenstudio/version.py b/samples/apps/autogen-studio/autogenstudio/version.py new file mode 100644 index 000000000000..70eac45bac15 --- /dev/null +++ b/samples/apps/autogen-studio/autogenstudio/version.py @@ -0,0 +1,2 @@ +VERSION = "0.0.11a" +APP_NAME = "autogenstudio" diff --git a/samples/apps/autogen-studio/autogenstudio/web/__init__.py b/samples/apps/autogen-studio/autogenstudio/web/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/samples/apps/autogen-studio/autogenstudio/web/app.py b/samples/apps/autogen-studio/autogenstudio/web/app.py new file mode 100644 index 000000000000..ce46a4192d4e --- /dev/null +++ b/samples/apps/autogen-studio/autogenstudio/web/app.py @@ -0,0 +1,362 @@ +import json +import os +import traceback +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware +from fastapi.staticfiles import StaticFiles +from fastapi import HTTPException + + +from ..datamodel import ( + ChatWebRequestModel, + DBWebRequestModel, + CreateSkillWebRequestModel, + DeleteMessageWebRequestModel, + Message, + Session, +) +from ..utils import md5_hash, init_webserver_folders, DBManager, dbutils + +from ..chatmanager import AutoGenChatManager + + +app = FastAPI() + + +# allow cross origin requests for testing on localhost:800* ports only +app.add_middleware( + CORSMiddleware, + allow_origins=[ + "http://localhost:8000", + "http://127.0.0.1:8000", + "http://localhost:8001", + "http://localhost:8081", + ], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + + +root_file_path = os.path.dirname(os.path.abspath(__file__)) +# init folders skills, workdir, static, files etc +folders = init_webserver_folders(root_file_path) + +api = FastAPI(root_path="/api") +# mount an api route such that the main route serves the ui and the /api +app.mount("/api", api) + +app.mount("/", StaticFiles(directory=folders["static_folder_root"], html=True), name="ui") +api.mount("/files", StaticFiles(directory=folders["files_static_root"], html=True), name="files") + + +db_path = os.path.join(root_file_path, "database.sqlite") +dbmanager = DBManager(path=db_path) # manage database operations +chatmanager = AutoGenChatManager() # manage calls to autogen + + +@api.post("/messages") +async def add_message(req: ChatWebRequestModel): + message = Message(**req.message.dict()) + user_history = dbutils.get_messages(user_id=message.user_id, session_id=req.message.session_id, dbmanager=dbmanager) + + # save incoming message to db + dbutils.create_message(message=message, dbmanager=dbmanager) + user_dir = os.path.join(folders["files_static_root"], "user", md5_hash(message.user_id)) + os.makedirs(user_dir, exist_ok=True) + + try: + response_message: Message = chatmanager.chat( + message=message, + history=user_history, + work_dir=user_dir, + flow_config=req.flow_config, + ) + + # save assistant response to db + dbutils.create_message(message=response_message, dbmanager=dbmanager) + response = { + "status": True, + "message": response_message.content, + "metadata": json.loads(response_message.metadata), + } + return response + except Exception as ex_error: + print(traceback.format_exc()) + return { + "status": False, + "message": "Error occurred while processing message: " + str(ex_error), + } + + +@api.get("/messages") +def get_messages(user_id: str = None, session_id: str = None): + if user_id is None: + raise HTTPException(status_code=400, detail="user_id is required") + try: + user_history = dbutils.get_messages(user_id=user_id, session_id=session_id, dbmanager=dbmanager) + + return { + "status": True, + "data": user_history, + "message": "Messages retrieved successfully", + } + except Exception as ex_error: + print(ex_error) + return { + "status": False, + "message": "Error occurred while retrieving messages: " + str(ex_error), + } + + +@api.get("/gallery") +def get_gallery_items(gallery_id: str = None): + try: + gallery = dbutils.get_gallery(gallery_id=gallery_id, dbmanager=dbmanager) + return { + "status": True, + "data": gallery, + "message": "Gallery items retrieved successfully", + } + except Exception as ex_error: + print(ex_error) + return { + "status": False, + "message": "Error occurred while retrieving messages: " + str(ex_error), + } + + +@api.get("/sessions") +def get_user_sessions(user_id: str = None): + """Return a list of all sessions for a user""" + if user_id is None: + raise HTTPException(status_code=400, detail="user_id is required") + + try: + user_sessions = dbutils.get_sessions(user_id=user_id, dbmanager=dbmanager) + + return { + "status": True, + "data": user_sessions, + "message": "Sessions retrieved successfully", + } + except Exception as ex_error: + print(ex_error) + return { + "status": False, + "message": "Error occurred while retrieving sessions: " + str(ex_error), + } + + +@api.post("/sessions") +async def create_user_session(req: DBWebRequestModel): + """Create a new session for a user""" + # print(req.session, "**********" ) + + try: + session = Session(user_id=req.session.user_id, flow_config=req.session.flow_config) + user_sessions = dbutils.create_session(user_id=req.user_id, session=session, dbmanager=dbmanager) + return { + "status": True, + "message": "Session created successfully", + "data": user_sessions, + } + except Exception as ex_error: + print(traceback.format_exc()) + return { + "status": False, + "message": "Error occurred while creating session: " + str(ex_error), + } + + +@api.post("/sessions/publish") +async def publish_user_session_to_gallery(req: DBWebRequestModel): + """Create a new session for a user""" + + try: + gallery_item = dbutils.create_gallery(req.session, tags=req.tags, dbmanager=dbmanager) + return { + "status": True, + "message": "Session successfully published", + "data": gallery_item, + } + except Exception as ex_error: + print(traceback.format_exc()) + return { + "status": False, + "message": "Error occurred while publishing session: " + str(ex_error), + } + + +@api.post("/messages/delete") +async def remove_message(req: DeleteMessageWebRequestModel): + """Delete a message from the database""" + + try: + messages = dbutils.delete_message( + user_id=req.user_id, msg_id=req.msg_id, session_id=req.session_id, dbmanager=dbmanager + ) + return { + "status": True, + "message": "Message deleted successfully", + "data": messages, + } + except Exception as ex_error: + print(ex_error) + return { + "status": False, + "message": "Error occurred while deleting message: " + str(ex_error), + } + + +@api.post("/cleardb") +async def clear_db(req: DBWebRequestModel): + """Clear user conversation history database and files""" + + # user_files_dir = os.path.join(folders["files_static_root"], "user", md5_hash(req.user_id)) + # user_skills_dir = os.path.join(folders["user_skills_dir"], md5_hash(req.user_id)) + + # delete_files_in_folder([user_files_dir]) + + try: + dbutils.delete_message( + user_id=req.user_id, msg_id=None, session_id=req.session.session_id, dbmanager=dbmanager, delete_all=True + ) + sessions = dbutils.delete_sessions(user_id=req.user_id, session_id=req.session.session_id, dbmanager=dbmanager) + return { + "status": True, + "data": { + "sessions": sessions, + }, + "message": "Messages and files cleared successfully", + } + except Exception as ex_error: + print(ex_error) + return { + "status": False, + "message": "Error occurred while deleting message: " + str(ex_error), + } + + +@api.get("/skills") +def get_user_skills(user_id: str): + try: + skills = dbutils.get_skills(user_id, dbmanager=dbmanager) + + return { + "status": True, + "message": "Skills retrieved successfully", + "data": skills, + } + except Exception as ex_error: + print(ex_error) + return { + "status": False, + "message": "Error occurred while retrieving skills: " + str(ex_error), + } + + +@api.post("/skills") +def create_user_skills(req: CreateSkillWebRequestModel): + """_summary_ + + Args: + user_id (str): the user id + skills (Skill[]): the skills to be created + + Returns: + _type_: dict + """ + + try: + skills = dbutils.create_skill(skill=req.skill, dbmanager=dbmanager) + + return { + "status": True, + "message": "Skills retrieved successfully", + "data": skills, + } + + except Exception as ex_error: + print(ex_error) + return { + "status": False, + "message": "Error occurred while creating skills: " + str(ex_error), + } + + +@api.get("/agents") +def get_user_agents(user_id: str): + try: + agents = dbutils.get_agents(user_id, dbmanager=dbmanager) + + return { + "status": True, + "message": "Agents retrieved successfully", + "data": agents, + } + except Exception as ex_error: + print(ex_error) + return { + "status": False, + "message": "Error occurred while retrieving agents: " + str(ex_error), + } + + +@api.post("/agents") +def create_user_agents(req: DBWebRequestModel): + """Create a new agent for a user""" + + try: + agents = dbutils.create_agent(agent_flow_spec=req.agent, dbmanager=dbmanager) + + return { + "status": True, + "message": "Agent created successfully", + "data": agents, + } + + except Exception as ex_error: + print(traceback.format_exc()) + return { + "status": False, + "message": "Error occurred while creating agent: " + str(ex_error), + } + + +@api.get("/workflows") +def get_user_workflows(user_id: str): + try: + workflows = dbutils.get_workflows(user_id, dbmanager=dbmanager) + + return { + "status": True, + "message": "Workflows retrieved successfully", + "data": workflows, + } + except Exception as ex_error: + print(ex_error) + return { + "status": False, + "message": "Error occurred while retrieving workflows: " + str(ex_error), + } + + +@api.post("/workflows") +def create_user_workflow(req: DBWebRequestModel): + """Create a new workflow for a user""" + + try: + workflow = dbutils.create_workflow(workflow=req.workflow, dbmanager=dbmanager) + return { + "status": True, + "message": "Workflow created successfully", + "data": workflow, + } + + except Exception as ex_error: + print(ex_error) + return { + "status": False, + "message": "Error occurred while creating workflow: " + str(ex_error), + } diff --git a/samples/apps/autogen-studio/autogenstudio/workflowmanager.py b/samples/apps/autogen-studio/autogenstudio/workflowmanager.py new file mode 100644 index 000000000000..7e119c98282a --- /dev/null +++ b/samples/apps/autogen-studio/autogenstudio/workflowmanager.py @@ -0,0 +1,143 @@ +from typing import List, Optional +from dataclasses import asdict +import autogen +from .datamodel import AgentFlowSpec, AgentWorkFlowConfig, Message +from .utils import get_skills_from_prompt + + +class AutoGenWorkFlowManager: + """ + AutoGenWorkFlowManager class to load agents from a provided configuration and run a chat between them + """ + + def __init__( + self, + config: AgentWorkFlowConfig, + history: Optional[List[Message]] = None, + work_dir: 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 or "work_dir" + self.sender = self.load(config.sender) + self.receiver = self.load(config.receiver) + + print("work_dir", self.work_dir) + + 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() + ) + skills_prompt = "" + if agent_spec.skills: + skills_prompt = get_skills_from_prompt(agent_spec.skills, self.work_dir) + + 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" + + skills_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, + ) diff --git a/samples/apps/autogen-studio/docs/ara_stockprices.png b/samples/apps/autogen-studio/docs/ara_stockprices.png new file mode 100644 index 0000000000000000000000000000000000000000..fafb830ef1a121eec1a9ebc488b56c01c233b22a GIT binary patch literal 198222 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∋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 z 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

k^{$;x-L%_qKraKp8Qjzv?<;fpl(b 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

    NhS=>WxZ~`#2Q9A)F{E&4}O{a?xuDn#Nd=& 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

    Re@Z=bqe5a~yLVTLtw|+kP5Sm%mnZ^xmPK2S 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 literal 0 HcmV?d00001 diff --git a/samples/apps/autogen-studio/frontend/.env.default b/samples/apps/autogen-studio/frontend/.env.default new file mode 100644 index 000000000000..da3ebffaa289 --- /dev/null +++ b/samples/apps/autogen-studio/frontend/.env.default @@ -0,0 +1,5 @@ + # use this for .env.development assuming your backend is running on port 8081 +GATSBY_API_URL=http://127.0.0.1:8081/api + +# use this .env.production assuming your backend is running on same port as frontend. Remember toremove these comments. +GATSBY_API_URL=/api diff --git a/samples/apps/autogen-studio/frontend/.gitignore b/samples/apps/autogen-studio/frontend/.gitignore new file mode 100644 index 000000000000..8a0ea868f24b --- /dev/null +++ b/samples/apps/autogen-studio/frontend/.gitignore @@ -0,0 +1,8 @@ +node_modules/ +.cache/ +public/ + +.env.development +.env.production + +yarn.lock diff --git a/samples/apps/autogen-studio/frontend/LICENSE b/samples/apps/autogen-studio/frontend/LICENSE new file mode 100644 index 000000000000..16ab6489c8ed --- /dev/null +++ b/samples/apps/autogen-studio/frontend/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Victor Dibia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/samples/apps/autogen-studio/frontend/README.md b/samples/apps/autogen-studio/frontend/README.md new file mode 100644 index 000000000000..7af58ee311ec --- /dev/null +++ b/samples/apps/autogen-studio/frontend/README.md @@ -0,0 +1,30 @@ +## 🚀 Running UI in Dev Mode + +Run the UI in dev mode (make changes and see them reflected in the browser with hotreloading): + +- npm install +- npm run start + +This should start the server on port 8000. + +## Design Elements + +- **Gatsby**: The app is created in Gatsby. A guide on bootstrapping a Gatsby app can be found here - https://www.gatsbyjs.com/docs/quick-start/. + This provides an overview of the project file structure include functionality of files like `gatsby-config.js`, `gatsby-node.js`, `gatsby-browser.js` and `gatsby-ssr.js`. +- **TailwindCSS**: The app uses TailwindCSS for styling. A guide on using TailwindCSS with Gatsby can be found here - https://tailwindcss.com/docs/guides/gatsby.https://tailwindcss.com/docs/guides/gatsby . This will explain the functionality in tailwind.config.js and postcss.config.js. + +## Modifying the UI, Adding Pages + +The core of the app can be found in the `src` folder. To add pages, add a new folder in `src/pages` and add a `index.js` file. This will be the entry point for the page. For example to add a route in the app like `/about`, add a folder `about` in `src/pages` and add a `index.tsx` file. You can follow the content style in `src/pages/index.tsx` to add content to the page. + +Core logic for each component should be written in the `src/components` folder and then imported in pages as needed. + +## connecting to front end + +the front end makes request to the backend api and expects it at /api on localhost port 8081 + +## setting env variables for the UI + +- please look at env.default +- make a copy of this file and name it `env.development` +- set the values for the variables in this file diff --git a/samples/apps/autogen-studio/frontend/gatsby-browser.js b/samples/apps/autogen-studio/frontend/gatsby-browser.js new file mode 100644 index 000000000000..b28e798f0d41 --- /dev/null +++ b/samples/apps/autogen-studio/frontend/gatsby-browser.js @@ -0,0 +1,6 @@ +import "antd/dist/reset.css"; +import "./src/styles/global.css"; + +import AuthProvider from "./src/hooks/provider"; + +export const wrapRootElement = AuthProvider; diff --git a/samples/apps/autogen-studio/frontend/gatsby-config.ts b/samples/apps/autogen-studio/frontend/gatsby-config.ts new file mode 100644 index 000000000000..047412b52470 --- /dev/null +++ b/samples/apps/autogen-studio/frontend/gatsby-config.ts @@ -0,0 +1,52 @@ +import type { GatsbyConfig } from "gatsby"; + +require("dotenv").config({ + path: `.env.${process.env.NODE_ENV}`, +}); + +const config: GatsbyConfig = { + pathPrefix: `${process.env.PREFIX_PATH_VALUE}`, + siteMetadata: { + title: `AutoGen Studio`, + description: `Build Multi-Agent Apps`, + siteUrl: `http://tbd.place`, + }, + flags: { + LAZY_IMAGES: true, + FAST_DEV: true, + DEV_SSR: false, + }, + plugins: [ + "gatsby-plugin-sass", + "gatsby-plugin-image", + "gatsby-plugin-sitemap", + "gatsby-plugin-postcss", + { + resolve: "gatsby-plugin-manifest", + options: { + icon: "src/images/icon.png", + }, + }, + "gatsby-plugin-mdx", + "gatsby-plugin-sharp", + "gatsby-transformer-sharp", + { + resolve: "gatsby-source-filesystem", + options: { + name: "images", + path: "./src/images/", + }, + __key: "images", + }, + { + resolve: "gatsby-source-filesystem", + options: { + name: "pages", + path: "./src/pages/", + }, + __key: "pages", + }, + ], +}; + +export default config; diff --git a/samples/apps/autogen-studio/frontend/gatsby-ssr.tsx b/samples/apps/autogen-studio/frontend/gatsby-ssr.tsx new file mode 100644 index 000000000000..7601c31d03ca --- /dev/null +++ b/samples/apps/autogen-studio/frontend/gatsby-ssr.tsx @@ -0,0 +1,16 @@ +import React from "react"; + +const codeToRunOnClient = `(function() { + try { + var mode = localStorage.getItem('darkmode'); + document.getElementsByTagName("html")[0].className === 'dark' ? 'dark' : 'light'; + } catch (e) {} +})();`; + +export const onRenderBody = ({ setHeadComponents }) => + setHeadComponents([ +