Skip to content

Integration of chat llm behavior #112

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

Merged
merged 33 commits into from
May 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
aae269a
skeleton
doumdi Feb 12, 2025
2147929
Adding ChatDesire and ChatStrategy, WIP.
doumdi Feb 17, 2025
41b2d34
Base chatbot demo
doumdi Feb 17, 2025
ece85d4
Demo enabling ChatStrategy working. WIP.
doumdi Feb 17, 2025
115d087
Working chat with ollama
doumdi Feb 19, 2025
c4019c7
Working chatbot
doumdi Feb 20, 2025
5e0c07e
Updated to ros2 branch
doumdi Feb 26, 2025
7568fc4
Merge branch 'ros2' of https://github.com/introlab/t-top into chat-llm
doumdi Feb 27, 2025
2f0edaa
Working ChatGPT with function calls, WIP.
doumdi Mar 3, 2025
2bc8bc1
Working simple function calls
doumdi Mar 3, 2025
1337637
Starting separation into configuration files
doumdi Apr 1, 2025
c042a6d
Merge branch 'ros2' of https://github.com/introlab/t-top into chat-llm
doumdi Apr 14, 2025
63c5450
Sending function calls from tools to publisher
doumdi Apr 14, 2025
07f0f1a
Calling external services, WIP
doumdi Apr 15, 2025
5ec34ef
Calling external services, WIP
doumdi Apr 15, 2025
2c26a5d
WIP, adding service to chatbot demo
doumdi Apr 15, 2025
3b459ed
Callbacks blocking after calling service, why ?
doumdi Apr 16, 2025
aa770de
Trying another thread, same result, not receiving subscriber message
doumdi Apr 16, 2025
56c2cd0
Workaround to avoid service call blocking the executor
doumdi Apr 23, 2025
7e91731
Working version to raise or lower volume
doumdi Apr 23, 2025
8a77196
Cleanup
doumdi Apr 23, 2025
e496b7b
Added documentation, cleanup launch files
doumdi Apr 24, 2025
c915ead
Updated documentation
doumdi Apr 25, 2025
3fc9285
Fixed pull request comments.
doumdi Apr 30, 2025
d051e8c
Address remaining pull request comments.
doumdi Apr 30, 2025
7bbd393
Fixing last things before merge
doumdi May 1, 2025
4fed255
Merge branch 'ros2' of https://github.com/introlab/t-top into chat-llm
doumdi May 1, 2025
1761561
Fix openai api for openai > 1.0.0
philippewarren May 1, 2025
31bce37
Merge branch 'chat-llm' of https://github.com/introlab/t-top into cha…
philippewarren May 1, 2025
5d87c02
Fixed typos, minor fix for pull request
doumdi May 9, 2025
aca84c9
Added new filter for chat behavior translation subscriber, republishi…
doumdi May 12, 2025
286f9ee
fixed documentation and filter activation order.
doumdi May 13, 2025
ba94117
fixed documentation.
doumdi May 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ros/behaviors/behavior_srvs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ find_package(rosidl_default_generators REQUIRED)
# Generate services
rosidl_generate_interfaces(${PROJECT_NAME}
"srv/GenerateSpeechFromText.srv"
"srv/ChatToolsFunctionCall.srv"
)

ament_package()
7 changes: 7 additions & 0 deletions ros/behaviors/behavior_srvs/srv/ChatToolsFunctionCall.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
string id
string type
string function_name
string function_arguments
---
bool ok
string result
46 changes: 46 additions & 0 deletions ros/behaviors/chat/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 3.5)
project(chat)

# Default to C99
if(NOT CMAKE_C_STANDARD)
set(CMAKE_C_STANDARD 99)
endif()

# Default to C++17
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 17)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# Find dependencies
find_package(ament_cmake REQUIRED)
find_package(audio_utils_msgs REQUIRED)
find_package(hbba_lite REQUIRED)
find_package(behavior_srvs REQUIRED)
find_package(behavior_msgs REQUIRED)
find_package(time_utils REQUIRED)

# Python Librairies
ament_python_install_package(${PROJECT_NAME})

# Python Nodes
install(PROGRAMS
scripts/chat_node.py
DESTINATION lib/${PROJECT_NAME}
)

# Configuration files
install(DIRECTORY
prompts
DESTINATION share/${PROJECT_NAME}/
)

install(DIRECTORY
tools
DESTINATION share/${PROJECT_NAME}/
)

ament_package()
66 changes: 66 additions & 0 deletions ros/behaviors/chat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# chat

This folder contains the node to make T-Top chat (LLM based). The node can be used with a local model or using the OpenAI API (paid service). Performance may vary depending on the model used and the embedded computer performance if ran locally.

## `chat_node.py`

This ROS2 node allows T-Top to communicate with the user using a large language model (LLM). It uses either an OpenAI model or a local model using Ollama. The local Ollama API is using the same chat completion API endpoints as the OpenAI API. Instead of connecting to external servers, it connects to the local ollama server at http://localhost:11434.

To reduce latency, the model is called in streaming mode. The node is designed to output the text to be spoken by the TTS module incrementally. Tools are called dynamically using the service name and the service message. The tools can be configured using a JSON file. Initial context can also be configured with a JSON file.

The `chat_node.py` is designed to be used in conjunction with a speech-to-text (STT) module and a text-to-speech (TTS) module. Listening or speaking is performed using an external HBBA node which controls desires, strategies and filters. A demo application can be found in the [demos/chatbot](../../demos/chatbot/README.md) folder.

### Requirements

- `openai` (Python package): The OpenAI API client.
```bash
# Python package dependencies sould be handled with rosdep for latest Ubuntu
rosdep install --from-paths src/t-top/ros/behaviors/chat/ --ignore-src -r -y
# Alternatively, you can install the package manually using pip
pip3 install openai
```
- `ollama` (optional) : Ollama can be installed from [ollama.com](https://ollama.com/). Local models can be downloaded from [ollama.com/models](https://ollama.com/models). [Installation instructions](https://ollama.com/download/linux) are available on the website.
```bash
# Install the ollama CLI, this will automatically setup the Jetson with an embedded server and API.
curl -fsSL https://ollama.com/install.sh | sh
# Download the model
ollama pull <model_name>
# You can test the model with the following command
ollama run <model_name> "Hello, how are you?"
```

> If you plan to use the OpenAI API, you need to set the `OPENAI_API_KEY` environment variable with your OpenAI API key. You can do this by running the following command in your terminal:
```bash
# This variable is already set on the T-Top's Jetson computer
export OPENAI_API_KEY=<your_openai_api_key>
```

### Parameters

- `language` (string) ['fr', 'en']. The language to use for the LLM. The default is 'fr' (French).
- `language_model` (string) default: 'gpt-4o-mini': The language model to use. The models can be found in the [ollama.com/models](https://ollama.com/models) website for local models or on [OpenAI website](https://platform.openai.com/docs/models). If you use ollama, make sure you download the model first using the `ollama pull <model_name>` command.
- `model_type` (string) ['ollama', 'chatgpt']: The model type to use. The default is 'chatgpt'.
- `enable_tools` (bool) default: True: Enable or disable the tools. The tools are used to call functions from the LLM. The tools can be configured using a JSON file.
- `tools_config` (string) default: `get_package_share_directory("chat") + "/tools/default_tools.json"`: The JSON file containing the tools configuration. The default files should be in the package share directory. The structure of the JSON file must follow OpenAI's function calling format. See the [OpenAI documentation](https://platform.openai.com/docs/guides/gpt/function-calling) for more information.
- `enable_prompts` (bool) default: True: Enable or disable the prompts. The prompts are used to configure the LLM. The prompts can be configured using a JSON file.
- `prompts_config` (string) default: `get_package_share_directory("chat") + "/prompts/default_<language>.json"`: The JSON file containing the prompts configuration. The default files should be in the package share directory.

### Subscribed Topics

- `chat/transcript` ([perception_msgs/Transcript](../../perceptions/perception_msgs/msg/Transcript.msg)): The text output by the Speech-to-Text (STT) perception module. This is used to trigger the chat API (processing the output of the LLM).
- `talk/done` ([behavior_msgs/Done](../behavior_msgs/msg/Done.msg)): Sent when the Text To Speech (TTS) module is done talking. This is used to trigger the next action to be performed by the chat behavior.

### Published Topics

- `talk/text` ([behavior_msgs/Text](../behavior_msgs/msg/Text.msg)): The text to be spoken by the TTS module. This is used to trigger the TTS module.
- `chat/done` ([behavior_msgs/Done](../behavior_msgs/msg/Done.msg)): Sent when the chat session is completed.

### Services

- (TODO) Clear the chat history. This is used to clear the chat history when the user says "clear" or "reset". This can also be triggered by external nodes.
- (TODO) Add information to the chat history. This can be useful to add more context to the chat session. This could also be done via a topic.

### Tools (Dynamic remote service calls)

If tools are enabled, external service calls are made using the following service name and using the following service message:
- `chat/tools/functions/{function_name}` ([behavior_srvs/ChatToolsFunctionCall](../behavior_srvs/srv/ChatToolsFunctionCall.srv)): The service is dynamically called according to the function name defined in the tools configuration file. The service must answer within 5 seconds and return a JSON response to be sent to the LLM.
Empty file.
5 changes: 5 additions & 0 deletions ros/behaviors/chat/launch/test_chat.launch.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<launch>
<node pkg="chat" exec="chat_node.py" name="chat_node">

</node>
</launch>
31 changes: 31 additions & 0 deletions ros/behaviors/chat/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>chat</name>
<version>0.0.0</version>
<description>LLM Chat bot</description>
<maintainer email="[email protected]">introlab</maintainer>
<license>GPL-3.0 license</license>

<buildtool_depend>ament_cmake</buildtool_depend>

<depend>rclpy</depend>
<depend>std_msgs</depend>
<depend>audio_utils_msgs</depend>
<depend>hbba_lite</depend>
<depend>behavior_srvs</depend>
<depend>behavior_msgs</depend>
<depend>time_utils</depend>
<exec_depend>python3-openai-pip</exec_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<exec_depend>ros2launch</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>

<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>

</package>
6 changes: 6 additions & 0 deletions ros/behaviors/chat/prompts/default_en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"role": "system",
"content": "You are a helpful assistant. You will be given a series of messages and you should respond to them in a helpful and informative manner."
}
]
6 changes: 6 additions & 0 deletions ros/behaviors/chat/prompts/default_fr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"role": "system",
"content": "Vous êtes un assistant utile. Vous recevrez une série de messages et vous devez y répondre de manière utile et informative."
}
]
Loading