Skip to content

Commit 9564f4f

Browse files
authored
Manipulation demo: Add streamlit interface (#337)
Signed-off-by: Kacper Dąbrowski <[email protected]>
1 parent 542616e commit 9564f4f

File tree

3 files changed

+129
-37
lines changed

3 files changed

+129
-37
lines changed

docs/demos/manipulation.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ This demo showcases the capabilities of RAI in performing manipulation tasks usi
5050
ros2 launch examples/manipulation-demo.launch.py game_launcher:=path/to/RAIManipulationDemo.GameLauncher
5151
```
5252

53-
2. In the second terminal, run the interactive prompt:
53+
2. In the second terminal, run the streamlit interface:
54+
55+
```shell
56+
streamlit run examples/manipulation-demo-streamlit.py
57+
```
58+
59+
Alternatively, you can run the simpler command-line version, which also serves as an example of how to use the RAI API for you own applications:
5460

5561
```shell
5662
python examples/manipulation-demo.py
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Copyright (C) 2024 Robotec.AI
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language goveself.rning permissions and
13+
# limitations under the License.
14+
15+
import importlib
16+
17+
import streamlit as st
18+
from langchain_core.messages import AIMessage, HumanMessage, ToolMessage
19+
20+
from rai.agents.integrations.streamlit import get_streamlit_cb, streamlit_invoke
21+
from rai.messages import HumanMultimodalMessage
22+
23+
manipulation_demo = importlib.import_module("manipulation-demo")
24+
25+
26+
@st.cache_resource
27+
def initialize_graph():
28+
return manipulation_demo.create_agent()
29+
30+
31+
def main():
32+
st.set_page_config(
33+
page_title="RAI Manipulation Demo",
34+
page_icon=":robot:",
35+
)
36+
st.title("RAI Manipulation Demo")
37+
st.markdown("---")
38+
39+
st.sidebar.header("Tool Calls History")
40+
41+
if "graph" not in st.session_state:
42+
graph = initialize_graph()
43+
st.session_state["graph"] = graph
44+
45+
if "messages" not in st.session_state:
46+
st.session_state["messages"] = [
47+
AIMessage(content="Hi! I am a robotic arm. What can I do for you?")
48+
]
49+
50+
prompt = st.chat_input()
51+
for msg in st.session_state.messages:
52+
if isinstance(msg, AIMessage):
53+
if msg.content:
54+
st.chat_message("assistant").write(msg.content)
55+
elif isinstance(msg, HumanMultimodalMessage):
56+
continue
57+
elif isinstance(msg, HumanMessage):
58+
st.chat_message("user").write(msg.content)
59+
elif isinstance(msg, ToolMessage):
60+
with st.sidebar.expander(f"Tool: {msg.name}", expanded=False):
61+
st.code(msg.content, language="json")
62+
63+
if prompt:
64+
st.session_state.messages.append(HumanMessage(content=prompt))
65+
st.chat_message("user").write(prompt)
66+
with st.chat_message("assistant"):
67+
st_callback = get_streamlit_cb(st.container())
68+
streamlit_invoke(
69+
st.session_state["graph"], st.session_state.messages, [st_callback]
70+
)
71+
72+
73+
if __name__ == "__main__":
74+
main()

examples/manipulation-demo.py

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
import rclpy
16+
import rclpy.qos
1617
from langchain_core.messages import HumanMessage
1718

1819
from rai.agents.conversational_agent import create_conversational_agent
@@ -21,45 +22,56 @@
2122
from rai.tools.ros.native import GetCameraImage, Ros2GetTopicsNamesAndTypesTool
2223
from rai.utils.model_initialization import get_llm_model
2324

24-
rclpy.init()
25-
node = RaiBaseNode(node_name="manipulation_demo")
26-
node.declare_parameter("conversion_ratio", 1.0)
2725

28-
tools = [
29-
GetObjectPositionsTool(
30-
node=node,
31-
target_frame="panda_link0",
32-
source_frame="RGBDCamera5",
33-
camera_topic="/color_image5",
34-
depth_topic="/depth_image5",
35-
camera_info_topic="/color_camera_info5",
36-
),
37-
MoveToPointTool(node=node, manipulator_frame="panda_link0"),
38-
GetCameraImage(node=node),
39-
Ros2GetTopicsNamesAndTypesTool(node=node),
40-
]
26+
def create_agent():
27+
rclpy.init()
28+
node = RaiBaseNode(node_name="manipulation_demo")
29+
node.declare_parameter("conversion_ratio", 1.0)
30+
node.qos_profile.reliability = rclpy.qos.ReliabilityPolicy.RELIABLE
4131

42-
llm = get_llm_model(model_type="complex_model")
32+
tools = [
33+
GetObjectPositionsTool(
34+
node=node,
35+
target_frame="panda_link0",
36+
source_frame="RGBDCamera5",
37+
camera_topic="/color_image5",
38+
depth_topic="/depth_image5",
39+
camera_info_topic="/color_camera_info5",
40+
),
41+
MoveToPointTool(node=node, manipulator_frame="panda_link0"),
42+
GetCameraImage(node=node),
43+
Ros2GetTopicsNamesAndTypesTool(node=node),
44+
]
4345

44-
system_prompt = """
45-
You are a robotic arm with interfaces to detect and manipulate objects.
46-
Here are the coordinates information:
47-
x - front to back (positive is forward)
48-
y - left to right (positive is right)
49-
z - up to down (positive is up)
46+
llm = get_llm_model(model_type="complex_model", streaming=True)
5047

51-
Before starting the task, make sure to grab the camera image to understand the environment.
52-
"""
48+
system_prompt = """
49+
You are a robotic arm with interfaces to detect and manipulate objects.
50+
Here are the coordinates information:
51+
x - front to back (positive is forward)
52+
y - left to right (positive is right)
53+
z - up to down (positive is up)
5354
54-
agent = create_conversational_agent(
55-
llm=llm,
56-
tools=tools,
57-
system_prompt=system_prompt,
58-
)
55+
Before starting the task, make sure to grab the camera image to understand the environment.
56+
"""
5957

60-
messages = []
61-
while True:
62-
prompt = input("Enter a prompt: ")
63-
messages.append(HumanMessage(content=prompt))
64-
output = agent.invoke({"messages": messages})
65-
output["messages"][-1].pretty_print()
58+
agent = create_conversational_agent(
59+
llm=llm,
60+
tools=tools,
61+
system_prompt=system_prompt,
62+
)
63+
return agent
64+
65+
66+
def main():
67+
agent = create_agent()
68+
messages = []
69+
while True:
70+
prompt = input("Enter a prompt: ")
71+
messages.append(HumanMessage(content=prompt))
72+
output = agent.invoke({"messages": messages})
73+
output["messages"][-1].pretty_print()
74+
75+
76+
if __name__ == "__main__":
77+
main()

0 commit comments

Comments
 (0)