-
Notifications
You must be signed in to change notification settings - Fork 590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add agent side ROS #82
base: rosllm
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,3 +12,18 @@ make html | |
``` | ||
|
||
There are also several helpful [tutorials](tutorials/) to help you get started with running and customizing Agent. | ||
|
||
|
||
## ROS interface | ||
|
||
To run the agent with Flask interface with ROS | ||
|
||
In conda environment using the following command: | ||
|
||
``` | ||
python ../src/agent/start.py task=ros_task method=direct [email protected]=human | ||
``` | ||
|
||
Replace the ``[email protected]=human`` with your actual model. | ||
|
||
In ROS environment follow the instruction in the ros_pange_agent packge |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# @package _global_ | ||
agent: | ||
prompt_builder: | ||
template_paths: | ||
- default | ||
|
||
|
||
task: | ||
_target_: agent.tasks.ros_task.ROSTask | ||
name: simplebot_test_env | ||
description: | ||
subtask: null | ||
version: v0.1 | ||
|
||
max_env_steps: 1 | ||
max_episodes: 100 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add newline at end of file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Now please answer the question. | ||
Answer in the format | ||
Answer: <answer> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import requests | ||
|
||
|
||
class RosApi: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't want this to be a ROS specific interface, ideally this should be able to communicate with other environments - maybe HttpApi? Make sure to update filename too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Documentation? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added: To change communication port, in |
||
|
||
# Defined on ros side | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. inconsistent indentation - use black to format code |
||
default_timeout = 3 * 60 # default timeout is 3 minutes | ||
|
||
def __init__(self, timeout=None): | ||
self.timeout = self.default_timeout if timeout is None else timeout | ||
self._response = None | ||
|
||
@staticmethod | ||
def bad_response(obs): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Documentation? |
||
return { | ||
"success": False, | ||
"done": True, | ||
"reward": 0, | ||
"obs": obs, | ||
} | ||
|
||
def send_action(self, action): | ||
url = "http://localhost:5000/llmreq" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. port number should be a parameter somewhere that the user can specify themselves, we can default to also There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. change to llmact There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add
with your actual IP address and port. |
||
self._response = None # reset response | ||
try: | ||
data = {"action": action} | ||
resp = requests.post(url, json=data, timeout=self.timeout) | ||
response = resp.json() | ||
except requests.exceptions.Timeout: | ||
response = self.bad_response("Request timeout.") | ||
except requests.exceptions.RequestException as e: | ||
response = self.bad_response(f"Request exception: {e}") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe include the traceback error, you can get this using import traceback
tb_err = traceback.format_exc() |
||
self._response = response | ||
|
||
def get_env_observation(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. change to get_observation |
||
url = "http://localhost:5000/rosenv" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need better name, and port as parameter also, documentation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cahnge to llmobs |
||
self._response = None # reset response | ||
try: | ||
data = {"": ""} | ||
resp = requests.post(url, json=data, timeout=self.timeout) | ||
response = resp.json() | ||
except requests.exceptions.Timeout: | ||
response = self.bad_response("Request timeout.") | ||
except requests.exceptions.RequestException as e: | ||
response = self.bad_response(f"Request exception: {e}") | ||
self._response = response | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. these functions look very similar, think about re-using code |
||
|
||
return response | ||
|
||
def get_feedback(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure we need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed |
||
url = "http://localhost:5000/rosfdb" | ||
self._response = None # reset response | ||
try: | ||
data = {"": ""} | ||
resp = requests.post(url, json=data, timeout=self.timeout) | ||
response = resp.json() | ||
except requests.exceptions.Timeout: | ||
response = self.bad_response("Request timeout.") | ||
except requests.exceptions.RequestException as e: | ||
response = self.bad_response(f"Request exception: {e}") | ||
self._response = response | ||
|
||
return response | ||
|
||
def receive_response(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. documentation? also, where is this used? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed |
||
assert self._response is not None, "did not receive a response" | ||
return self._response |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
from agent.tasks import Task | ||
from .ros_api import RosApi | ||
from typing import Any, Dict | ||
import warnings | ||
|
||
|
||
class ROSTask(Task): | ||
|
||
def __init__(self, **kwargs): | ||
super().__init__(**kwargs) | ||
self.ros_api = RosApi() | ||
print(self.ros_api) | ||
self.response = {"reward": 0.0, | ||
"done": False, | ||
"obs": ""} | ||
self.possible_actions = [] | ||
|
||
def answer_parser(self, raw_response: str): | ||
return raw_response | ||
|
||
def is_complete(self): | ||
return self.response['done'] | ||
|
||
def reset(self, next_subtask: str | None = None) -> Dict[str, str]: | ||
"""Reset the environment and return the initial observation.""" | ||
|
||
if next_subtask is not None: | ||
warnings.warn("ros_task does not support subtasks, ignoring subtask") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this a warning case or failing case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed |
||
|
||
response= self.ros_api.get_env_observation() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. format code with black |
||
|
||
return { | ||
"_text_obs": response, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why the underscore? looks ugly, maybe this is to do with ninja or related to agent code? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed |
||
"_available_actions": self.possible_actions | ||
} | ||
|
||
def get_observation(self): | ||
obs = self.ros_api.get_env_observation() | ||
fdb = self.ros_api.get_feedback() | ||
Comment on lines
+38
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i dont see any need for two function, this can be merged into a single function and then we can handle the human-feedback on the ROS side There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed |
||
return { | ||
"_available_actions": obs, | ||
"_available_actions": fdb | ||
} | ||
|
||
def step(self, action): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. documentation? |
||
print(action) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove print statement There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed |
||
self.ros_api.send_action(action) | ||
self.response = self.ros_api.receive_response() | ||
print(self.response['obs']) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove print statement Also, it would be good to have a way to save this data, @AntGro does the agent code have functionality for automatically saving prompts/responses? Perhaps this is a flag that we can set somewhere? Otherwise, I suggest we add this - would be useful to add somewhere in the agent code, but I am not sure where would be best? |
||
return {}, self.response["reward"], self.response["done"] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,8 +17,6 @@ Huawei, Noah's Ark Lab. | |
- [Enhancing Reinforcement Learning Agents with Local Guides](RLLG) | ||
- [Sauté RL and Simmer RL: Safe Reinforcement Learning Using Safety State Augmentation ](./SIMMER) | ||
- [Model-Based Offline Reinforcement Learning with Pessimism-Modulated Dynamics Belief](./PMDB) | ||
- Robotics Research | ||
- [ROS-LLM: A ROS framework for embodied AI with task feedback and structured reasoning](./ROSLLM) | ||
Comment on lines
-20
to
-21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. revert, we want this to appear There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added |
||
|
||
Further instructions are provided in the README files associated to each project. | ||
|
||
|
@@ -91,7 +89,7 @@ design, and logic synthesis for electronic design automation. | |
## [RDUCB: High Dimensional Bayesian Optimisation with Random Decompositions](./RDUCB) | ||
|
||
<p align="center"> | ||
<img src="./RDUCB/figures/ToyProblem.PNG" width="400" /> | ||
<img src="./RDUCB/figures/ToyProblem.PNG" width="400" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove trailing whitespace There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is from HEBO readme, I don't think we should change it |
||
</p> | ||
|
||
Codebase associated | ||
|
@@ -168,7 +166,7 @@ efficiency and QoR values. | |
|
||
<p float="center"> | ||
<img src="./T-LBO/figures/LSBO.png" width="400" /> | ||
<img src="./T-LBO/figures/magnets.png" width="400" /> | ||
<img src="./T-LBO/figures/magnets.png" width="400" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove trailing whitespace There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is from HEBO readme, I don't think we should change it |
||
</p> | ||
|
||
Codebase associated | ||
|
@@ -306,12 +304,3 @@ policy-dependent reweighting factor, termed *Pessimism-Modulated Dynamics Belief | |
iterative regularized policy optimization algorithm for the game, with guarantee of monotonous improvement under certain | ||
condition. To make practical, we further devise an offline RL algorithm to approximately find the solution. Empirical | ||
results show that the proposed approach achieves state-of-the-art performance on a wide range of benchmark tasks. | ||
|
||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
|
||
## Codebase Contributors | ||
|
||
<strong> Current contributors: </strong> Antoine Grosnit, Alexandre Max Maravel, Taher Jafferjee, Wenlong Lyu, Kaiyang Guo, Juliusz Ziomek, Paul Daoudi, Merwan Barlier, Christopher E. Mower. | ||
|
||
<strong> Alumni / External contributors: </strong> Alexander I. Cowen-Rivers, Kamil Dreczkowski, Aivar Sootla, Ryan Rhys Griffiths, Zhi Wang, Ludovic Dos Santos, Bogdan Robu, Christophe Prieur. | ||
|
||
Comment on lines
-309
to
-317
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should not have been removed, I am not sure how this happened? Anyway, please revert and also @W9YBZ you can add your name to current contributors. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
cmake_minimum_required(VERSION 3.0.2) | ||
project(ros_agent) | ||
|
||
find_package(catkin REQUIRED COMPONENTS | ||
rospy | ||
std_msgs | ||
message_generation | ||
) | ||
|
||
# catkin_python_setup() | ||
|
||
add_service_files( | ||
FILES | ||
HandleAgentAction.srv | ||
) | ||
|
||
generate_messages( | ||
DEPENDENCIES | ||
std_msgs | ||
) | ||
|
||
catkin_package( | ||
CATKIN_DEPENDS message_runtime | ||
) | ||
|
||
include_directories( | ||
${catkin_INCLUDE_DIRS} | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add new line at end of document There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Agent interface | ||
|
||
This packge allow you to communicate with the Agent | ||
|
||
## Documentation | ||
|
||
### To start the Flask communication node: | ||
In ROS environment run | ||
|
||
``` | ||
python ../scripts/ros_agent_node.py | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do not use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changed |
||
``` | ||
|
||
Please refer the document in the agent for strating the agent. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
|
||
### To stop the node: | ||
Tpye ``exit`` in the human input | ||
Comment on lines
+16
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo and add space after section header There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changed |
||
|
||
## Examples: | ||
To publish current time to the obsercvation: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
In ROS environment run | ||
|
||
``` | ||
python ../example/publish_time.py | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changed |
||
``` | ||
|
||
|
||
To strat the action service: | ||
In ROS environment run | ||
|
||
``` | ||
python ../example/agentactionservice.py | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#!/usr/bin/env python | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i dont like the naming for this file, use underscore for spaces, also There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changed |
||
import rospy | ||
from ros_agent.srv import HandleAgentAction, HandleAgentActionResponse | ||
|
||
def handle_action(req): | ||
""" | ||
Process the action request and return the response. | ||
This function simulates action processing by returning a success status, | ||
a message, and a reward. | ||
""" | ||
print("Received action request: {}".format(req.action)) | ||
|
||
# Here you would add the logic to process the action, e.g., controlling a robot or running an algorithm | ||
response_message = "Action processed successfully" | ||
reward = 1.0 # Example fixed reward; adjust based on actual action processing logic | ||
|
||
return HandleAgentActionResponse(success=True, response=response_message, reward=reward) | ||
|
||
def action_service(): | ||
rospy.init_node('agent_action_service') | ||
|
||
# Create the service 'handle_agent_action' and specify the handler function | ||
s = rospy.Service('handle_agent_action', HandleAgentAction, handle_action) | ||
|
||
print("Service 'handle_agent_action' ready to handle requests.") | ||
rospy.spin() # Keep the service open. | ||
|
||
if __name__ == "__main__": | ||
action_service() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/usr/bin/env python3 | ||
import rospy | ||
from std_msgs.msg import String | ||
import datetime | ||
|
||
def publish_timestamp(): | ||
rospy.init_node('timestamp_publisher', anonymous=True) | ||
publisher = rospy.Publisher('agent_environment', String, queue_size=10) | ||
rate = rospy.Rate(5) # Frequency of 1 Hz | ||
|
||
while not rospy.is_shutdown(): | ||
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") | ||
rospy.loginfo(f"Publishing current timestamp: {current_time}") | ||
publisher.publish(current_time) | ||
rate.sleep() | ||
|
||
if __name__ == '__main__': | ||
try: | ||
publish_timestamp() | ||
except rospy.ROSInterruptException: | ||
pass |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?xml version="1.0"?> | ||
<package format="2"> | ||
<name>ros_agent</name> | ||
<version>0.0.0</version> | ||
<description>The ros_agent package</description> | ||
|
||
<maintainer email="[email protected]">hyu</maintainer> | ||
<maintainer email="[email protected]">cmower</maintainer> | ||
|
||
<license>TODO</license> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MIT |
||
|
||
<author email="[email protected]">hyu</author> | ||
<author email="[email protected]">cmower</author> | ||
|
||
<buildtool_depend>catkin</buildtool_depend> | ||
<depend>rospy</depend> | ||
<depend>std_msgs</depend> | ||
<build_depend>message_generation</build_depend> | ||
<exec_depend>message_runtime</exec_depend> | ||
|
||
</package> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from flask import Flask, request, jsonify | ||
|
||
app = Flask(__name__) | ||
|
||
@app.route('/', methods=['POST']) | ||
def receive_string(): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. documentation? |
||
if request.method == 'POST': | ||
# Receive the JSON data | ||
data = request.get_json() | ||
|
||
# Extract the string from the JSON data | ||
received_string = data.get('msg') | ||
|
||
# Prompt the user to input another string | ||
user_input_string = input(f"{received_string}\n") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is the only point for this script to get input from the user for feedback/task-description? If so, then we will move to using chat window and this script becomes redundant let me know if this script has any other useage? otherwise remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed command_window.py |
||
|
||
# Prepare the response JSON data | ||
response_data = { | ||
'received_string': received_string, | ||
'user_input_string': user_input_string | ||
} | ||
return jsonify(response_data) | ||
|
||
if __name__ == '__main__': | ||
app.run(host='0.0.0.0', port=5002, debug=True, use_reloader=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specify where the user should change directory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to follow the tutorials in last step