Skip to content

Instantly share code, notes, and snippets.

@slintak
Last active June 5, 2024 20:12
Show Gist options
  • Save slintak/2f99b5aeae363c86a68a74c72b3293d7 to your computer and use it in GitHub Desktop.
Save slintak/2f99b5aeae363c86a68a74c72b3293d7 to your computer and use it in GitHub Desktop.
Meshtastic AI Chat Assistant Integration

This gist contains a proof of concept project (hacked together during one evening) aimed at connecting an AI chat assistant to the Meshtastic network, enhancing its capabilities. The assistant is designed to provide concise and helpful responses within the constraints of the Meshtastic environment.

Project Overview:

This project brings together two favorite elements: the Meshtastic network and an AI chat assistant. The assistant is based on the "FuseChat-7B-VaRM-Q5_K_M" model, and the code is written in Python.

The code is optimized to run on an ordinary PC without a GPU. I tested it on my old i5-2400 CPU with 16 GB of RAM. In such cases, responses may take around 30-60 seconds.

Functionality:

The assistant receives packet payload, Received Signal Strength Indication (RSSI), and Signal-to-Noise Ratio (SNR) from the Meshtastic network. It generates responses with a maximum length of 237 characters, aiming to be concise and helpful.

Getting Started:

To run the project, ensure you have Python installed along with the AI model and required dependencies specified in requirements.txt. Additionally, make sure to have Meshtastic devices set up and connected to the USB or to the network.

Usage:

  1. Clone this repository to your local machine.
  2. Install dependencies using pip install -r requirements.txt.
  3. Download model huggingface-cli download LoneStriker/FuseChat-7B-VaRM-GGUF FuseChat-7B-VaRM-Q5_K_M.gguf --local-dir ./models --local-dir-use-symlinks False
  4. Run the Python script main.py.

Notes:

This project is just a proof of concept and may require further tweaking for optimal performance. Any feedback is welcome; feel free to reach out. Enjoy exploring Meshtastic with AI assistance!

If you enjoy this project, be sure to check out my other creation, MakerDeals.eu. This website simplifies the process of finding, filtering, and comparing 3D printing filaments available on Amazon.

import time
from meshtastic.tcp_interface import TCPInterface
from meshtastic.serial_interface import SerialInterface
from llama_cpp import Llama
from pubsub import pub
PROMPT = '''
You are an assistant working on the Meshtastic LoRa network.
You can respond in English or Czech languages.
Your responses are straight to the point, short, helpful and mostly one sentence.
The maximum length of your response is 237 characters.
Input from the user contains signal quality information as a JSON object.
These are for context and should not be repeated in the response!
'''
llm = Llama(
model_path="./models/FuseChat-7B-VaRM-Q5_K_M.gguf",
n_threads=4,
use_mmap=True,
use_mlock=True,
n_ctx=4048,
)
def onReceive(packet, interface):
data = packet.get('decoded')
if data.get('portnum') == 'TEXT_MESSAGE_APP':
payload = data.get('payload', b'').decode('utf-8')
rssi = packet['rxRssi'] or '?'
snr = packet['rxSnr'] or '?'
content = f'{payload} {{"rssi":"{rssi} dBm","snr":"{snr} dB"}}'
output = llm.create_chat_completion(
messages=[
{"role": "system", "content": PROMPT},
{"role": "user", "content": content},
]
)
response = output["choices"][0]["message"]["content"]
print(f"Received: {content}")
print(f"Response: {response}\n")
interface.sendText(response)
def onConnection(interface, topic=pub.AUTO_TOPIC):
# interface.sendText("AI assistant is alive!")
pass
pub.subscribe(onReceive, "meshtastic.receive")
pub.subscribe(onConnection, "meshtastic.connection.established")
interface = SerialInterface(devPath='/dev/ttyACM0')
# interface = TCPInterface(hostname='192.168.0.2', connectNow=True)
while True:
print('Idle.')
time.sleep(60)
interface.close()
huggingface-hub>=0.17.1
llama-cpp-python
meshtastic
@cfaulkingham
Copy link

Thanks for sharing this. I was planning on trying this myself you saved me some effort.

This works pretty well if you want to send the whole response in multiple messages. As long as you not connected to anything but your local devices.

for i in range(0, len(response), 225):
           interface.sendText(response[i:i+225])

I am also using TheBloke/Mistral-7B-Instruct-v0.2-GGU which runs great using my RTX 3090 on Win11.

llm = Llama(
    model_path="./models/mistral-7b-instruct-v0.2.Q8_0.gguf",
    n_gpu_layers=-1,
)

@cfaulkingham
Copy link

cfaulkingham commented Mar 29, 2024

Also, for those you trying to get llama-cpp-python working on Win11 with Cuda;
so you can run this with your GPU instead of your CPU.

You need to install the following,

  1. Visual Studio CE - https://visualstudio.microsoft.com/vs/community/
  2. Cuda Toolkit - https://developer.nvidia.com/cuda-toolkit
set FORCE_CMAKE=1
set CMAKE_ARGS="-DLLAMA_CUBLAS=on"
set CUDACXX="C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.4\bin\nvcc.exe"
pip install llama-cpp-python[server] --upgrade --force-reinstall --no-cache-dir

@DrBlackross
Copy link

DrBlackross commented Jun 3, 2024

keep getting an error...

Model metadata: {'tokenizer.chat_template': "{{ bos_token }}{% for message in messages %}{{ 'GPT4 Correct ' + message['role'].title() + ': ' + message['content'] + '<|end_of_turn|>'}}{% endfor %}{% if add_generation_prompt %}{{ 'GPT4 Correct Assistant:' }}{% endif %}", 'tokenizer.ggml.add_eos_token': 'false', 'tokenizer.ggml.unknown_token_id': '0', 'tokenizer.ggml.eos_token_id': '32000', 'general.architecture': 'llama', 'llama.rope.freq_base': '10000.000000', 'llama.context_length': '8192', 'general.name': 'models', 'tokenizer.ggml.add_bos_token': 'true', 'llama.embedding_length': '4096', 'llama.feed_forward_length': '14336', 'llama.attention.layer_norm_rms_epsilon': '0.000010', 'llama.rope.dimension_count': '128', 'tokenizer.ggml.bos_token_id': '1', 'llama.attention.head_count': '32', 'llama.block_count': '32', 'llama.attention.head_count_kv': '8', 'general.quantization_version': '2', 'tokenizer.ggml.model': 'llama', 'general.file_type': '17'}
Available chat formats from metadata: chat_template.default
Using gguf chat template: {{ bos_token }}{% for message in messages %}{{ 'GPT4 Correct ' + message['role'].title() + ': ' + message['content'] + '<|end_of_turn|>'}}{% endfor %}{% if add_generation_prompt %}{{ 'GPT4 Correct Assistant:' }}{% endif %}
Using chat eos_token: <|end_of_turn|>
Using chat bos_token: <s>
Idle.
Exception in thread Thread-3:
Traceback (most recent call last):
  File "~/miniconda/lib/python3.12/threading.py", line 1073, in _bootstrap_inner
    self.run()
  File "~/miniconda/lib/python3.12/threading.py", line 1431, in run
    self.function(*self.args, **self.kwargs)
  File "~/miniconda/lib/python3.12/site-packages/meshtastic/mesh_interface.py", line 687, in callback
    self._sendToRadio(p)
  File "~/miniconda/lib/python3.12/site-packages/meshtastic/mesh_interface.py", line 746, in _sendToRadio
    self._sendToRadioImpl(toRadio)
  File "~/miniconda/lib/python3.12/site-packages/meshtastic/stream_interface.py", line 115, in _sendToRadioImpl
    self._writeBytes(header + b)
  File "~/miniconda/lib/python3.12/site-packages/meshtastic/tcp_interface.py", line 72, in _writeBytes
    self.socket.send(b)
BrokenPipeError: [Errno 32] Broken pipe
^CTraceback (most recent call last):
  File "~/Desktop/Lora-Projects/Lora-Ai/./main.py", line 59, in <module>
    time.sleep(1000)
KeyboardInterrupt
warning: failed to munlock buffer: Cannot allocate memory

something has, changed... but, the only thing i changed was i switched it over to TCP, and updated the firmware to the latest as of this date.

def onConnection(interface, topic=pub.AUTO_TOPIC):
    # interface.sendText("AI assistant is alive!")
    pass


pub.subscribe(onReceive, "meshtastic.receive")
pub.subscribe(onConnection, "meshtastic.connection.established")
#interface = SerialInterface(devPath='/dev/ttyUSB0')
interface = TCPInterface(hostname='192.168.1.34', connectNow=True)

rolling back to 2.3.9.f06c56a from 2.3.11.2740a56

ALSO, had to turn on JSON output for it to work in Mqtt module

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment