Skip to content

Commit

Permalink
Improves the examples so they're fully runnable
Browse files Browse the repository at this point in the history
Adds READMEs with basic instructions.
  • Loading branch information
elijahbenizzy committed Feb 9, 2024
1 parent 63ae384 commit af5a62e
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 15 deletions.
12 changes: 8 additions & 4 deletions burr/integrations/streamlit.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ def prior_actions(self) -> List[str]:
return out

@property
def next_action(self) -> str:
def next_action(self) -> Optional[str]:
if self.display_index < len(self.history) - 1:
return self.history[self.display_index + 1].action
if self.app.get_next_action() is None:
return None
return self.app.get_next_action().name # return the future one

@property
Expand Down Expand Up @@ -122,9 +124,11 @@ def lighten_color(color, amount=0.5):
lightened_color = colorsys.hls_to_rgb(c[0], 1 - amount * (1 - c[1]), c[2])
return mc.to_hex(lightened_color)

seen = {current_node}
digraph.node(current_node, fillcolor="darkgreen", style="rounded,filled", fontcolor="white")
digraph.node(next_node, fillcolor="blue", style="rounded,filled", fontcolor="white")
seen = {current_node, next_node}
if next_node is not None:
digraph.node(next_node, fillcolor="blue", style="rounded,filled", fontcolor="white")
seen.add(next_node)
base_color = "lightblue"
for i, node in enumerate(prior_nodes):
if node not in seen:
Expand Down Expand Up @@ -272,7 +276,7 @@ def stringify(i):
# TODO -- consider a callback here instead
app_state.display_index = current_node_index

with placeholder.container(height=800):
with placeholder.container(height=900):
state_machine_view, step_view, data_view = st.tabs(
["Application", "Action", "State/Results"]
)
Expand Down
25 changes: 25 additions & 0 deletions examples/counter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Counter

This is an example of a simple state machine.

We have three files:

- [application.py](application.py) -- This contains a mainline to run the counter as well as a function to export the counter (for later use)
- [requirements.txt](requirements.txt) -- Just the requirements. All this needs is Burr/Streamlit
- [streamlit_app.py](streamlit_app.py) -- This contains a simple Streamlit app to interact with the counter.

To run just the application, you can run:

```bash
python application.py
```

To run the streamlit app, you can run:

```bash
streamlit run streamlit_app.py
```

This will open a chrome window and print out the URL. The state machine this encapsulates takes the following form:

![State Machine](digraph.png)
2 changes: 1 addition & 1 deletion examples/counter/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ def application(count_up_to: int = 10, log_file: str = None):
if __name__ == "__main__":
app = application(log_file="counter.jsonl")
state, result = app.run(until=["result"])
app.visualize(output_file_path="counter.png", include_conditions=True, view=True)
app.visualize(output_file_path="digraph", include_conditions=True, view=True, format="png")
assert state["counter"] == 10
print(state["counter"])
Binary file added examples/counter/digraph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 17 additions & 5 deletions examples/counter/streamlit_app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import counter
import application as counter
import streamlit as st

from burr.integrations.streamlit import (
Expand Down Expand Up @@ -36,16 +36,28 @@ def retrieve_state():

def main():
st.set_page_config(layout="wide")
st.title("Counting numbers with Burr")
app_state = retrieve_state() # retrieve first so we can use for the ret of the step
columns = st.columns(2)
with columns[0]:
sidebar = st.sidebar
with sidebar:
st.markdown(
"""
<style>
section[data-testid="stSidebar"] {
width: 400px !important; # Set the width to your desired value
}
</style>
""",
unsafe_allow_html=True,
)
st.title("Counting numbers with Burr")
st.write(
"This is a simple counter app. It counts to 10, then loops back to 0. You can reset it at any time. "
"While we know that this is easy to do with a simple loop + streamlit, it highlights the state that Burr manages."
"Use the slider to rewind/see what happened in the past, and the visualizations to understand how we navigate "
"through the state machine!"
)
app_state = retrieve_state() # retrieve first so we can use for the ret of the step
columns = st.columns(2)
with columns[0]:
counter_view(app_state)
with st.container(height=800):
md_lines = []
Expand Down
28 changes: 28 additions & 0 deletions examples/cowsay/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Cowsay

This is an example of a simple infinite state machine.

We have three files:

- [application.py](application.py) -- This contains a mainline to run the cowsay app as well as a function to export the app (for later use)
- [requirements.txt](requirements.txt) -- Just the requirements. All this needs is Burr/Streamlit/cowsay
- [streamlit_app.py](streamlit_app.py) -- This contains a simple Streamlit app to interact with the cow

To run just the application, you can run:

```bash
python application.py
```

Note this is an infinte state machine, so this will run forever! Thus remember to ctrl-c eventually.
To run the streamlit app, you can run:

```bash
streamlit run streamlit_app.py
```

This allows you to press a button and see the cow say something (or see it decide not to speak).

This will open a chrome window and print out the URL. The state machine this encapsulates takes the following form:

![State Machine](digraph.png)
2 changes: 1 addition & 1 deletion examples/cowsay/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,6 @@ def application(in_terminal: bool = False) -> Application:

if __name__ == "__main__":
app = application(in_terminal=True)
app.visualize(output_file_path="cowsay.png", include_conditions=True, view=True)
app.visualize(output_file_path="digraph", include_conditions=True, view=True, format="png")
while True:
s, r, action = app.step()
Binary file added examples/cowsay/digraph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions examples/gpt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# GPT-like chatbot

This is an example of chatgpt-like bot. It is simplified, but demonstrates the core concepts nicely.

The core idea is that we:

1. Accept a prompt
2. Check to see if the prompt is "safe" (this is currently a no-op, but its there for show)
3. Decide the response mode by querying openAI (answer a question, generate an image, write some code, and can't decide/prompt for more)
4. Query one of our models with a modified prompt to return the right response
5. Return the response
6. Go back to the beginning and wipe the state.

We have both a hamilton and non-hamilton implementation of this for comparison. For the simplicity of this example,
Hamilton is likely overkill. There are a few nodes that could leverage it well, but the rest are too simple to
worry about putting in a DAG. As examples get more complex, we anticipate that Hamilton nodes will play a more important role.

The state machine this encapsulates takes the following form:

![State Machine](digraph.png)


Note that it is currently wired up to handle errors in the state machine, but the actions do not respect that yet. Coming soon.

We have three files:

- [application.py](application.py) -- This contains a mainline to generate the graph portrayal.
- [requirements.txt](requirements.txt) -- Just the requirements. All this needs is Burr/Streamlit/openai
- [streamlit_app.py](streamlit_app.py) -- This contains a simple Streamlit app to interact with the cow


You must have your `OPENAI_API_KEY` set in your environment. You can do this by running.

To run on streamlit, you can launch the app:

```bash
streamlit run streamlit_app.py
```

This allows you to input a prompt, watch it "think", and explore the history/"why" of the response.
5 changes: 1 addition & 4 deletions examples/gpt/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,4 @@ def application(use_hamilton: bool, hooks: List[LifecycleAdapter] = []) -> Appli

if __name__ == "__main__":
app = application(use_hamilton=False)
# state, result = app.run(until=["result"])
app.visualize(output_file_path="gpt", include_conditions=False, view=True, format="png")
# assert state["counter"] == 10
# print(state["counter"])
app.visualize(output_file_path="digraph", include_conditions=False, view=True, format="png")
Binary file added examples/gpt/digraph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions examples/gpt/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
burr[streamlit]
openai

0 comments on commit af5a62e

Please sign in to comment.