Skip to main content

1. Make your own LLM peripheral

What You'll Need

Hardware

  • ESP32 board (ESP32-C3 Mini, ESP32-CAM, or any Wi-Fi capable model)

Software

Other

  • USB cable
  • Text editor (VSCode recommended)

Project Setup

1. Download the SDK

git clone https://github.com/kawaiiTaiga/project_SABA.git
cd project_SABA

2. Create PlatformIO Project

  1. Create a new project in PlatformIO
  2. Delete the src/main.cpp file
  3. Copy contents from SDK's device_sdk/ folder to your project

3. Add Library Dependencies

Add to your platformio.ini file:

lib_deps =
bblanchon/ArduinoJson@^7.0.4
knolleary/PubSubClient@^2.8

Building Your First Tool

The core of SABA is semantic function design. Define what your device does, not how it controls hardware.

Traditional vs SABA Approach

Traditional Approach:

motor.rotate(50, CLOCKWISE, 100);  // How many degrees for a door?
led.setRGB(255, 200, 150); // Which LED is this?

SABA Approach:

openLivingRoomDoor();              // Clear location and intent
setCinematicLighting(); // Specific use case

Exercise: Creating a Lighting Control Tool

You only need to modify three files.

1. Implement Tool Logic (modules/my_lighting.cpp)

#include "my_lighting.h"

JsonDocument MyLighting::getSchema() {
JsonDocument schema;
schema["type"] = "object";
schema["properties"]["intensity"]["type"] = "string";
schema["properties"]["intensity"]["enum"] = JsonArray({"gentle", "normal", "bright"});
return schema;
}

JsonDocument MyLighting::execute(const JsonDocument& args) {
String intensity = args["intensity"] | "normal";

// Hardware control logic
if (intensity == "gentle") {
analogWrite(LED_PIN, 64);
} else if (intensity == "bright") {
analogWrite(LED_PIN, 255);
} else {
analogWrite(LED_PIN, 128);
}

JsonDocument result;
result["text"] = "Lighting adjusted to " + intensity + " intensity";
return result;
}

2. Declare Interface (modules/my_lighting.h)

#pragma once
#include "ITool.h"

class MyLighting : public ITool {
public:
JsonDocument getSchema() override;
JsonDocument execute(const JsonDocument& args) override;
};

3. Register Tool (modules/tool_register.cpp)

#include "tool_register.h"
#include "my_lighting.h"

void register_tools(ToolRegistry& reg, const ToolConfig& cfg) {
reg.addTool("adjust_room_lighting", std::make_unique<MyLighting>());
// Add other tools here...
}

Important: The register_tools function must be defined exactly once per project.


Semantic Function Naming Guide

Good function names should be immediately understandable by LLMs.

Principles

Include Location

  • openLivingRoomDoor
  • openDoor

Specify Use Case

  • setCinematicLighting
  • setWarmLight

Reflect User Intent

  • checkRoomComfort
  • readTemperature

Embed Purpose

  • prepareMovieNight
  • dimLights

Examples

When a user says "open the living room door," the LLM should immediately recognize openLivingRoomDoor().

When they say "prepare for movie night," it should find prepareMovieNight().

Function names are the bridge between natural language and device capabilities.


Result Format

Always return meaningful feedback:

JsonDocument result;
result["text"] = "Living room door opened successfully";
result["assets"] = JsonArray(); // For images, files, etc.
return result;

Build and Upload

1. Build

Build your project in PlatformIO:

pio run

2. Upload

Upload to ESP32:

pio run --target upload

3. Check Serial Monitor

pio device monitor

Next Steps

Once your device is successfully built and uploaded, it's time to connect it to SABA Core.