{{ name }}
====================

Welcome to this LLM chatbot example! It uses `ollama` to bridge your ROS 2
application with an LLM.

What are the next steps?

## Prerequisites

Before being able to use this bridge, you need to install `ollama` and the
`ollama` python bindings:

- install `ollama`: https://ollama.com/download
- download a LLM model. For instance: `ollama pull llama3.2:1b`
- start `ollama` as a server: `ollama server`

> Note: you can configure `ollama` to [start at startup](https://github.com/ollama/ollama/blob/main/docs/linux.md#adding-ollama-as-a-startup-service-recommended).

- install the `ollama` python bindings: `pip install ollama`

## Compile and install {{id}}

You need a ROS 2 environment to compile the template.

You can for instance use PAL Robotics public 'tutorials' Docker image:

```
> docker pull palrobotics/public-tutorials-alum-devel
> docker run -it --name ros2_sandbox \
             -v <path to your workspace>:/home/user/exchange/ws \
             palrobotics/public-tutorials-alum-devel bash
```

Then, simply run:

```
> cd /home/user/exchange/ws
> colcon build
> source install/setup.bash
```

You can now start the bridge with:

```
> ros2 launch {{id}} {{id}}.launch.py
```

## Testing

You can test the application from the terminal by publishing some input speech, and monitoring the
`/intents` topic for results.

In a second terminal, run:

```
ros2 topic echo /intents
```

> Note: you can open a new terminal in the same Docker image with:
> ```
> docker exec -it ros2_sandbox bash
> ```

Then (from a third terminal) let's pretend that a voice is heard by the robot:

```
ros2 topic pub -1 /humans/voices/tracked hri_msgs/msg/IdsList "ids: ['test_speaker']"
```

Then:

```
ros2 topic pub -1 /humans/voices/test_speaker/speech hri_msgs/msg/LiveSpeech "final: 'hello robot, what can you do for me?'"
```

You should now see intents being published, based on what the LLM chatbot has recognised.

## Customizing the bridge

The bridge's behaviour can be customize via two main means: parameters, and code improvements.

### Custom prompt

The prompt used by the bridge is configure with the `system_prompt` parameter (see `config/00-defaults.yml`).

You can modify it directly in `config/00-defaults.yml` (in that case, you need to re-install the node
after each modification), or you can provide a parameter override, located by default in `$HOME/.pal/config`:

Create the following file:

```
> mkdir -p $HOME/.pal/config
> nano $HOME/.pal/config/custom_llm_prompt.yml
```

And copy-paste the following:

```
/{{id}}:
  ros__parameters:
    server_url: 'http://localhost:11434' # URL of the ollama server
    model: llama3.2:1b # model (or model family) name
    system_prompt: |
        This is a new custom prompt. Modify it as you want.

        You can also use the template slots {action_list}, {environment} and
        {person_id} that will be replaced at runtime.
```

The main advantage of the override is that you do not need to re-install the
node. Simply stop and start it again to use the new prompt.

> Note: you can also change here the LLM model and `ollama` server URL if you
> wish.

### Extend the template code

The generated template is using a pretty simple approach to extract intents from the
user input.

Check `{{id}}/node_impl.py` to see how this is done, and implement your own
techniques.

