Skip to content

Commit ee1df68

Browse files
committed
Update docs to include maze runner demo
1 parent b76495c commit ee1df68

File tree

15 files changed

+499
-10
lines changed

15 files changed

+499
-10
lines changed

.github/workflows/docs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ jobs:
3232
- name: Convert notebooks to markdown for docs
3333
run: |
3434
jupyter nbconvert --to markdown "examples/cookbook.ipynb" --output-dir="docs/cookbook"
35+
jupyter nbconvert --to markdown "examples/maze_runner.ipynb" --output-dir="docs/cookbook/examples"
3536
3637
- name: Commit changes
3738
run: |

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ idea_evaluator = AIFunction("BusinessIdeaAnalyzer-XYZ123") # Replace with your a
4949
response = idea_evaluator("A subscription service for personalized, AI-generated bedtime stories for children.").output
5050
```
5151

52-
- The `aifn.build` function enables quick and easy prototyping of new AI functions that use foundation models as thier core. We encourage users to do this through our [platform](https://www.aifunction.com) for maximum control and ease of use, however, you can also do this through our API as shown [here](examples/cookbook.ipynb).
52+
- The `aifn.build` function enables quick and easy prototyping of new AI functions that use foundation models as their core. We encourage users to do this through our [platform](https://www.aifunction.com) for maximum control and ease of use, however, you can also do this through our API as shown [here](examples/cookbook.ipynb).
5353
- `aifn.AIFunction` allows you to retrieve an AI function you've already created.
5454
- Finally, as shown in the example above, `AIFunction` objects are akin to any function that we are used to...the only difference is that they have a large language model to power them!
5555

docs/assets/ai_function_dark.png

1.55 KB
Loading

docs/assets/ai_function_light.png

2.38 KB
Loading

docs/cookbook/cookbook.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,7 @@ output, metadata = task_evaluator("I want to train a model to predict house pric
212212
for key, value in output.items(): print(f"{key}: {value}")
213213
for i, step in enumerate(metadata["reasoning_steps"]): print(f"Step {i+1}: {step}")
214214
```
215+
216+
## End-to-End Examples
217+
218+
For more on what AI functions can do, check out these [examples](examples/maze_runner.md).

docs/cookbook/examples/maze_runner.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Maze Runner
2+
3+
*AI functions can navigate mazes*
4+
5+
In this tutorial, we're going to walk you through how AI functions can interact with games using simply images from the game. To do this, we will use OpenAI's [Procgen Benchmark](https://openai.com/index/procgen-benchmark/), specifically the 2D maze environment and [AI functions](https://www.aifunction.com/) by Weco. We'll build an agent that uses AI functions at it's core. Lets jump right in!
6+
7+
You can follow along through the code and also watch our quick demo on the same:
8+
<iframe width="640" height="360" src="https://www.youtube.com/embed/DLZ6lhxAFYU" frameborder="0" allowfullscreen></iframe>
9+
10+
<a href="https://colab.research.google.com/github/WecoAI/aifn-python/blob/main/examples/maze_runner.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" width=110 height=20/></a>
11+
<a target="_blank" href="https://lightning.ai/new?repo_url=https%3A%2F%2Fgithub.com%2FWecoAI%2Faifn-python%2Fblob%2Fmain%2Fexamples%2Fmaze_runner.ipynb"><img src="https://pl-bolts-doc-images.s3.us-east-2.amazonaws.com/app-2/studio-badge.svg" alt="Open in Studio" width=100 height=20/></a>
12+
13+
## Dependencies
14+
15+
16+
```python
17+
%%capture
18+
!apt-get update -qq
19+
!apt-get install -y software-properties-common
20+
!add-apt-repository ppa:openjdk-r/ppa -y
21+
!apt-get update -qq
22+
!apt-get install -y xvfb python3-opengl ffmpeg
23+
!pip install --no-cache-dir aifn Pillow gym procgen pyvirtualdisplay
24+
```
25+
26+
27+
```python
28+
import io
29+
from datetime import datetime
30+
import base64
31+
from copy import deepcopy
32+
import numpy as np
33+
import matplotlib.pyplot as plt
34+
from PIL import Image
35+
from IPython.display import clear_output
36+
from pyvirtualdisplay import Display
37+
from procgen import ProcgenEnv
38+
from aifn import AIFunction
39+
import warnings
40+
warnings.filterwarnings("ignore")
41+
```
42+
43+
## Setup Game
44+
45+
46+
```python
47+
def show_frame(observation, log_history):
48+
"""Helper function to display the current frame and command log."""
49+
clear_output(wait=True)
50+
fig = plt.figure(figsize=(10, 7))
51+
gs = fig.add_gridspec(1, 2, width_ratios=[3, 1])
52+
ax_left = fig.add_subplot(gs[0])
53+
ax_left.imshow(observation['rgb'][0])
54+
ax_left.axis('off')
55+
ax_right = fig.add_subplot(gs[1])
56+
ax_right.axis('off')
57+
ax_right.set_facecolor('#f7f7f7')
58+
ax_right.set_title("Command Log", loc='center', fontsize=12, pad=10, color='black')
59+
log_text = "\n".join("> " + s for s in log_history)
60+
ax_right.text(0, 1, log_text, ha='left', va='top', fontsize=10, family='monospace', color='black', wrap=True)
61+
plt.tight_layout()
62+
plt.show()
63+
```
64+
65+
66+
```python
67+
%%capture
68+
display = Display(visible=0, size=(1400, 900))
69+
display.start()
70+
```
71+
72+
73+
```python
74+
# Create our game environment
75+
env = ProcgenEnv(num_levels=1, start_level=20, use_backgrounds=False, distribution_mode="easy", num_envs=1, env_name="maze")
76+
```
77+
78+
## Build Agent
79+
80+
First, head on over to our [platform](https://www.aifunction.com/function/new) and create an AI function with the following description:
81+
> You are a grey blob navigating a treacherous 2D maze. Your only way out is to follow the dark road that leads to the orange exit. Return an 'action' that follows the path leading to the exit. Use 1 for left, 7 for right, 5 for up and 3 for down.
82+
83+
<!-- ![Maze Runner GIFs.gif](../docs/assets/maze_runner_create_fn.gif) -->
84+
![Maze Runner GIFs.gif](<maze_runner_files/Maze Runner GIFs.gif>)
85+
86+
Then grab the function name and come right back here to bring your agent to life!
87+
88+
![Maze Runner GIFs Copy Function Name.gif](<maze_runner_files/Maze Runner GIFs cpy fn.gif>)
89+
90+
We now define a class that uses an AI function at it's very core. The agent here is a simple wrapper around our AI function to provide a more agentic like interface for the game we are about to play. The core function takes in an observation (image), preprocesses this image and passes it to our AI function. The AI function then analyzes the image and returns a simple response. We can then extract and perform the action based on the AI function's judgement.
91+
92+
93+
```python
94+
class Agent:
95+
def __init__(self, fn_name, api_key):
96+
# Initialize your AI function
97+
self.get_action = AIFunction(fn_name=fn_name, api_key=api_key)
98+
99+
def __repr__(self): return str(self.get_action)
100+
def __str__(self): return str(self.get_action)
101+
102+
def act(self, observation):
103+
# Preprocess the observation
104+
resized_image = Image.fromarray(deepcopy(observation)['rgb'][0].astype(np.uint8)).resize((1024, 1024))
105+
buffer = io.BytesIO()
106+
resized_image.save(buffer, format="jpeg")
107+
images = [f"data:image/jpeg;base64,{base64.b64encode(buffer.getvalue()).decode('utf-8')}"]
108+
action = self.get_action(images_input=images).output["action"]
109+
return action
110+
111+
def action_to_command(self, action):
112+
action_space = {1: "left", 7: "right", 5: "up", 3: "down"}
113+
return action_space.get(action, "unknown")
114+
```
115+
116+
117+
```python
118+
# NOTE: Don't forget to set these!
119+
api_key = "YOUR_API_KEY"
120+
fn_name = "YOUR_AI_FUNCTION_NAME"
121+
122+
# Initialize our agent that uses an AI function as its brain
123+
agent = Agent(fn_name, api_key)
124+
print(f"Agent {agent} is on the job!")
125+
```
126+
127+
## Play the Game!
128+
129+
Now you're ready to play the game!
130+
131+
132+
```python
133+
# We'll give the agent 20 timesteps to navigate the maze but you could give it more if you'd like
134+
timesteps = 20
135+
observation = env.reset()
136+
137+
log_history = [f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Agent started navigating the maze"]
138+
show_frame(observation, log_history)
139+
140+
found = False # Did the agent find the exit yet?
141+
while timesteps > 0:
142+
# Determine the agent's next move based on the current state of the environment
143+
action = agent.act(observation)
144+
# Observe the results of the agent's action by getting the new state of the environment
145+
observation, _, done, _ = env.step(np.array([action]))
146+
timesteps -= 1
147+
148+
log_history.append(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Agent says move {agent.action_to_command(action)}.")
149+
show_frame(observation, log_history)
150+
151+
if done[0]:
152+
# The agent found the exit!
153+
found = True
154+
break
155+
156+
log_history.append(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Agent found the exit!" if found else f"Agent did not find the exit.")
157+
show_frame(observation, log_history)
158+
```
159+
160+
161+
```python
162+
%%capture
163+
env.close()
164+
display.stop()
165+
```
Loading
Loading

docs/getting_started/installation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,6 @@ If you need help getting started, you can check out any of the following resourc
3838
- [Introduction](introduction.md)
3939
- [Cookbook](../cookbook/cookbook.md)
4040
- [API Reference](../api/api.md)
41+
- [End-to-End Examples](../cookbook/examples/maze_runner.md)
4142

4243
Happy building!

docs/getting_started/introduction.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ Now you can call your AI function, just like any other function, anywhere in you
3939
response = idea_evaluator("A subscription service for personalized, AI-generated bedtime stories for children.")
4040
```
4141

42-
To learn how to get the most your of **your** AI functions, check out our [cookbook](../cookbook/cookbook.md) and [API reference](../api/api.md).
42+
To learn how to get the most your of **your** AI functions, check out our [cookbook](../cookbook/cookbook.md), our [API reference](../api/api.md) and these end-to-end [examples](../cookbook/examples/maze_runner.md).
4343

4444
Happy building!

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@ idea_evaluator = AIFunction("BusinessIdeaAnalyzer-XYZ123") # Replace with your a
4747
response = idea_evaluator("A subscription service for personalized, AI-generated bedtime stories for children.").output
4848
```
4949

50-
To learn how to get the most your of **your** AI functions, check out our [cookbook](cookbook//cookbook.md) and [API reference](api/api.md).
50+
To learn how to get the most your of **your** AI functions, check out our [cookbook](cookbook/cookbook.md), our [API reference](api/api.md) and these end-to-end [examples](cookbook/examples/maze_runner.md).
5151

5252
Happy building!

docs/stylesheets/extra.css

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/* Style links in the main content */
22
main a {
3-
color: #FF5722 !important; /* Highlight links in orange */
3+
color: #F55D2A !important; /* Highlight links in new base orange */
44
text-decoration: none; /* Remove underline */
55
}
66

77
main a:hover, main a:focus {
8-
color: #E64A19 !important; /* Slightly darker orange on hover */
8+
color: #FF5722 !important; /* Slightly darker orange on hover */
99
text-decoration: none; /* Ensure no underline */
1010
}
1111

@@ -16,7 +16,7 @@ nav[aria-label="Table of contents"] a {
1616
}
1717

1818
nav[aria-label="Table of contents"] a:hover, nav[aria-label="Table of contents"] a:focus {
19-
color: #FF5722 !important; /* Change text to orange on hover */
19+
color: #F55D2A !important; /* Change text to new base orange on hover */
2020
text-decoration: none; /* Ensure no underline */
2121
}
2222

@@ -27,7 +27,7 @@ header a, .md-header-nav a, .md-nav__item a {
2727
}
2828

2929
header a:hover, header a:focus, .md-header-nav a:hover, .md-header-nav a:focus, .md-nav__item a:hover, .md-nav__item a:focus {
30-
color: #FF5722 !important; /* Change text to orange on hover */
30+
color: #F55D2A !important; /* Change text to new base orange on hover */
3131
text-decoration: none; /* Ensure no underline */
3232
}
3333

@@ -38,7 +38,7 @@ nav[aria-label="Navigation"] a {
3838
}
3939

4040
nav[aria-label="Navigation"] a:hover, nav[aria-label="Navigation"] a:focus {
41-
color: #FF5722 !important; /* Change text to orange on hover */
41+
color: #F55D2A !important; /* Change text to new base orange on hover */
4242
text-decoration: none; /* Ensure no underline */
4343
}
4444

@@ -49,6 +49,6 @@ footer a {
4949
}
5050

5151
footer a:hover, footer a:focus {
52-
color: #FF5722 !important; /* Change text to orange on hover */
52+
color: #F55D2A !important; /* Change text to new base orange on hover */
5353
text-decoration: none; /* Ensure no underline */
5454
}

examples/cookbook.ipynb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,20 @@
354354
"for key, value in output.items(): print(f\"{key}: {value}\")\n",
355355
"for i, step in enumerate(metadata[\"reasoning_steps\"]): print(f\"Step {i+1}: {step}\")"
356356
]
357+
},
358+
{
359+
"cell_type": "markdown",
360+
"metadata": {},
361+
"source": [
362+
"## End-to-End Examples"
363+
]
364+
},
365+
{
366+
"cell_type": "markdown",
367+
"metadata": {},
368+
"source": [
369+
"For more on what AI functions can do, check out these [examples](.)."
370+
]
357371
}
358372
],
359373
"metadata": {

0 commit comments

Comments
 (0)