From 82da9c188de62e7f22ee1f38bfaa899e3bda67c0 Mon Sep 17 00:00:00 2001 From: Andrew Zhu Date: Wed, 17 Jul 2024 14:54:15 -0700 Subject: [PATCH] chore: some organization for dist --- .readthedocs.yaml | 23 +++++++++++++ README.md | 71 +++++++++++++++++++++++++++++++++++----- redel/app.py | 2 +- redel/config.py | 6 ++++ redel/eventlogger.py | 3 +- redel/server/.gitignore | 1 + redel/server/__main__.py | 2 ++ redel/server/server.py | 8 ++--- server.py | 2 +- viz/package.json | 3 +- 10 files changed, 103 insertions(+), 18 deletions(-) create mode 100644 .readthedocs.yaml create mode 100644 redel/server/.gitignore diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..aedd3bd74 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,23 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.10" + +# Build documentation in the "docs/" directory with Sphinx +sphinx: + configuration: docs/conf.py + +# Optional but recommended, declare the Python requirements required +# to build your documentation +# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +python: + install: + - requirements: requirements.txt diff --git a/README.md b/README.md index da74de8fc..46e5299fb 100644 --- a/README.md +++ b/README.md @@ -27,16 +27,69 @@ TODO ## Usage -TODO - -- how to change the delegation policy -- how to change the engine -- how to change the prompt -- how to add additional functions -- how to set which functions are always included in a delegate -- other options +There are two primary ways to interact with a system: interactively, through the web +interface, or programmatically. The former is particularly useful to debug your system's behaviour, iterate on prompts, +or otherwise provide an interactive experience. The latter is useful for running experiments and batch queries. + +See the docs for more usage information at https://redel.readthedocs.io! + +### Server + +```python +from kani.engines.openai import OpenAIEngine +from redel import AUTOGENERATE_TITLE +from redel.server import VizServer +from redel.tools.browsing import Browsing + +# Define the LLM engines to use for each node +engine = OpenAIEngine(model="gpt-4", temperature=0.8, top_p=0.95) + +# Define the configuration for each interactive session +redel_config = dict( + root_engine=engine, + delegate_engine=engine, + title=AUTOGENERATE_TITLE, + tool_configs={ + Browsing: {"always_include": True}, + }, +) + +# configure and start the server +server = VizServer(redel_kwargs=redel_config) +server.serve() +``` -## Defining Your Own Modules +### Programmatic + +```python +import asyncio +from kani import ChatRole +from kani.engines.openai import OpenAIEngine +from redel import ReDel, events +from redel.tools.browsing import Browsing + +# Define the LLM engines to use for each node +engine = OpenAIEngine(model="gpt-4", temperature=0.8, top_p=0.95) + +# Define the configuration for the session +ai = ReDel( + root_engine=engine, + delegate_engine=engine, + title="Airspeed of a swallow", + tool_configs={ + Browsing: {"always_include": True}, + }, +) + +# ReDel is async, so define an async function and use asyncio.run() +async def main(): + async for event in ai.query("What is the airspeed velocity of an unladen swallow?"): + if isinstance(event, events.RootMessage) and event.msg.role == ChatRole.ASSISTANT: + if event.msg.text: + print(event.msg.text) + +asyncio.run(main()) +``` ## EMNLP Demo Experiments diff --git a/redel/app.py b/redel/app.py index d40a1b50f..365295806 100644 --- a/redel/app.py +++ b/redel/app.py @@ -80,7 +80,7 @@ def __init__( :param title: The title of this session. Set to ``redel.AUTOGENERATE_TITLE`` to automatically generate one (default), or ``None`` to disable title generation. :param log_dir: A path to a directory to save logs for this session. Defaults to - ``.redel/instances/{session_id}/``. + ``$REDEL_HOME/instances/{session_id}/`` (default ``~/.redel/instances/{session_id}``). :param clear_existing_log: If the log directory has existing events, clear them before writing new events. Otherwise, append to existing events. :param session_id: The ID of this session. Generally this should not be set manually; it is used for loading diff --git a/redel/config.py b/redel/config.py index c8c061af1..e721731b5 100644 --- a/redel/config.py +++ b/redel/config.py @@ -2,10 +2,16 @@ from pathlib import Path # ==== core ==== +REDEL_HOME = Path(os.getenv("REDEL_HOME", "~/.redel")).expanduser() + # caching of embeddings, etc REDEL_CACHE_DIR = Path(os.getenv("REDEL_CACHE", "~/.cache/redel")).expanduser() REDEL_CACHE_DIR.mkdir(parents=True, exist_ok=True) +# log instances to ~/.redel/instances by default +DEFAULT_LOG_DIR = REDEL_HOME / "instances" +DEFAULT_LOG_DIR.mkdir(parents=True, exist_ok=True) + # ==== voice ==== ELEVEN_API_KEY = os.getenv("ELEVEN_API_KEY") ELEVEN_VOICE_ID = os.getenv("ELEVEN_VOICE_ID") diff --git a/redel/eventlogger.py b/redel/eventlogger.py index a2b10af25..7ac67f7ce 100644 --- a/redel/eventlogger.py +++ b/redel/eventlogger.py @@ -6,13 +6,12 @@ from typing import TYPE_CHECKING from . import events +from .config import DEFAULT_LOG_DIR from .utils import read_jsonl if TYPE_CHECKING: from .app import ReDel -DEFAULT_LOG_DIR = pathlib.Path(__file__).parents[1] / ".redel/instances" -DEFAULT_LOG_DIR.mkdir(parents=True, exist_ok=True) log = logging.getLogger(__name__) diff --git a/redel/server/.gitignore b/redel/server/.gitignore new file mode 100644 index 000000000..37efa8ff2 --- /dev/null +++ b/redel/server/.gitignore @@ -0,0 +1 @@ +/viz_dist/ diff --git a/redel/server/__main__.py b/redel/server/__main__.py index 3ba7f3417..d9e6a9f11 100644 --- a/redel/server/__main__.py +++ b/redel/server/__main__.py @@ -11,6 +11,8 @@ logging.basicConfig(level=logging.INFO) log = logging.getLogger("redel-server") +# todo args for save dirs + # Define the configuration for each interactive session redel_config = dict( title=AUTOGENERATE_TITLE, diff --git a/redel/server/server.py b/redel/server/server.py index f94d7fa22..975b46c7c 100644 --- a/redel/server/server.py +++ b/redel/server/server.py @@ -9,14 +9,14 @@ from fastapi.staticfiles import StaticFiles from redel import ReDel -from redel.eventlogger import DEFAULT_LOG_DIR +from redel.config import DEFAULT_LOG_DIR from redel.events import Error, SendMessage from redel.utils import read_jsonl from .indexer import find_saves from .models import SaveMeta, SessionMeta, SessionState from .session_manager import SessionManager -REPO_ROOT = Path(__file__).parents[1] +VIZ_DIST = Path(__file__).parent / "viz_dist" log = logging.getLogger("server") @@ -30,7 +30,7 @@ def __init__( ): """ :param save_dirs: A list of paths to scan for ReDel saves to make available to load. Defaults to - ``.redel/instances/``. + ``~/.redel/instances/``. :param redel_kwargs: Keyword arguments to supply to the :class:`.ReDel` constructor for each interactive session. Defaults to an empty dictionary. If this is set, ``redel_factory`` must not be set. :param redel_factory: An asynchronous function that creates a new :class:`.ReDel` instance when called. @@ -193,4 +193,4 @@ async def ws_interactive(websocket: WebSocket, session_id: str): await websocket.send_text(Error(msg=str(e)).model_dump_json()) # viz static files - self.fastapi.mount("/", StaticFiles(directory=REPO_ROOT / "viz/dist", html=True), name="viz") + self.fastapi.mount("/", StaticFiles(directory=VIZ_DIST, html=True), name="viz") diff --git a/server.py b/server.py index 80bef45df..ec99de3c3 100644 --- a/server.py +++ b/server.py @@ -18,7 +18,7 @@ from kani.ext.ratelimits import RatelimitedEngine from redel import AUTOGENERATE_TITLE -from redel.eventlogger import DEFAULT_LOG_DIR +from redel.config import DEFAULT_LOG_DIR from redel.server import VizServer from redel.tools.browsing import Browsing diff --git a/viz/package.json b/viz/package.json index 192659766..3149ff1e1 100644 --- a/viz/package.json +++ b/viz/package.json @@ -4,7 +4,8 @@ "private": true, "scripts": { "dev": "vite", - "build": "run-p type-check build-only && cp dist/index.html dist/404.html", + "build": "run-p type-check build-only", + "postbuild": "cp dist/index.html dist/404.html && cp -a dist/. ../redel/server/viz_dist/.", "preview": "vite preview", "build-only": "vite build", "type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",