LLMBTPLG

January 27, 2026 · View on GitHub

Python FastAPI

A web interface for controlling Intiface Central devices using LM Studio. Experience AI-controlled haptic feedback through natural language interaction with local LLMs.


Features

Core Functionality

  • Natural Language Control: AI embeds vibration commands directly in conversation
  • Real-Time Visualization: Live vibration graph with smooth 60 FPS rendering
  • Emotion System: Color-coded AI responses with 14+ customizable emotions
  • Macro System: Create, save, and reuse complex vibration patterns
  • Autonomous Mode: Hands-free pattern generation with configurable intervals
  • Manual Testing: Direct control sliders for immediate device testing

Safety and Privacy

  • Local LLM: All processing happens on your machine (LM Studio)
  • Emergency Stop: Instant halt button with queue clearing
  • Queue Visibility: See pending commands before execution
  • Intensity Caps: Built-in safety limits to prevent device damage

Technical Highlights

  • Streaming Chat: Real-time token-by-token AI responses
  • Command Parsing: Regex-based extraction of stroke() and wait() commands
  • Multi-Device Support: Control multiple toys simultaneously
  • WebSocket Architecture: <100ms latency from AI output to device
  • Responsive UI: Clean 2-column layout, works on mobile

Prerequisites

Required Software

  1. LM Studio (Free)

    • Download and install LM Studio
    • Load your preferred model
    • Start the Local Server (default port 1234)
    • ✅ Verify server is running at http://localhost:1234
  2. Intiface Central (Free)

    • Download and install Intiface Central
    • Start the server (default port 12345)
    • Connect your Bluetooth/USB devices
    • ✅ Ensure devices show as connected
  3. Python 3.10+

    • Download from python.org
    • ✅ Verify with python --version

Installation

Quick Start

# Clone the repository
git clone https://github.com/cyongjin37/LLMBTPLG.git
cd LLMBTPLG

# Install dependencies
pip install -r requirements.txt

# Start the server
python server.py

First Run

  1. Open your browser to http://127.0.0.1:8000
  2. Check Connection Status in the right panel:
    • ✅ Intiface Central should show "Active (X Devices)"
    • ✅ LM Studio should show "Active"
  3. Click Test Vibration to verify device control
  4. Start chatting with the AI!

Usage Guide

Basic Chat

Simply type a message and the AI will respond. The AI can embed vibration commands naturally:

You: "Can you tease me a little?"
AI: "Of course... let me start gently stroke(1000, 0.3) 
     How does that feel?"

Command Syntax

The AI uses these commands (you don't need to type them):

  • stroke(duration, intensity) - Vibrate for specified time

    • duration: milliseconds (e.g., 1000 = 1 second)
    • intensity: 0.0 to 1.0 (e.g., 0.5 = 50% power)
  • wait(duration) - Pause for specified time

    • duration: milliseconds
  • Macros - Reusable patterns:

    • set_sequence("name", [stroke(500,1), wait(200)])
    • call_sequence("name")
    • delete_sequence("name")

Control Panel Features

Connection Status

  • Intiface Central: Shows device count and connection state
  • LM Studio: Verify LLM server connectivity
  • Quick reconnect buttons if needed

Test Controls

  • Duration Slider: 100ms to 5000ms
  • Intensity Slider: 0% to 100%
  • Test Button: Immediate device response
  • Stop Button: Emergency halt

Device Settings

  • Oscillation: Toggle vibration pulsing mode
  • Remote Vibrator Mode: AI outputs pattern commands only (no dialogue)

Autonomous Mode

  • Auto-Reply: AI continues generating patterns automatically
  • Wait Interval: 1-60 seconds between generations
  • Force Chat: Manually trigger next AI response

Settings (Collapsible)

  • Prompt Management: Save/load custom roleplay scenarios
  • Emotion Settings: Add/remove emotion tags with colors
  • Dynamic Context: View auto-generated AI instructions

Emotion System

The AI can express emotions by starting responses with tags:

[Happy] That feels great!
[Teasing] Oh, you like that? stroke(500, 0.8)

Default Emotions: Neutral, Happy, Satisfied, Angry, Sad, Passionate, Dominant, Teasing, Love, Excited, Scared, Surprised, Begging, Disappointed

Custom Emotions: Add your own in Settings → Emotion Settings


Macro System Examples

Simple Pulse

set_sequence("pulse", [stroke(200, 1), wait(100), stroke(200, 1)])
call_sequence("pulse")

Complex Pattern

set_sequence("waves", [
  stroke(500, 0.3),
  stroke(500, 0.6),
  stroke(500, 0.9),
  wait(1000),
  stroke(1000, 0.5)
])

Quick Tease

set_sequence("tease", [stroke(300, 0.4), wait(500), stroke(300, 0.8)])

Advanced Configuration

Changing Ports

Edit server.py to modify default ports:

DEFAULT_LM_STUDIO_URL = "http://localhost:1234/v1"  # LM Studio
DEFAULT_ROUTER_PORT = 8769                           # Stroke server

Edit stroke.py for Intiface Central:

intiface_central_port = "12345"  # Intiface Central

Custom Prompts

  1. Navigate to Settings → Prompt Management
  2. Enter filename
  3. Write your custom roleplay prompt
  4. Click Save
  5. Select from dropdown and click Load

Architecture

[Browser] ←HTTP→ [FastAPI Server] ←WS→ [Stroke Server] ←Buttplug→ [Intiface] ←BT/USB→ [Devices]

         [LM Studio]
  • Frontend: Vanilla JavaScript with Canvas visualization
  • Backend: FastAPI with streaming support
  • Device Control: Async Python with buttplug-py
  • AI Integration: OpenAI-compatible API (LM Studio)

Troubleshooting

Intiface Central shows "Disconnected"

  • ✅ Ensure Intiface Central is running
  • ✅ Check server is on port 12345
  • ✅ Click "Reconnect" button (waits 10s for device scan)
  • ✅ Verify devices are paired in Bluetooth settings

LM Studio shows "Error"

  • ✅ Ensure LM Studio server is running
  • ✅ Check port 1234 is accessible
  • ✅ Try changing URL in the textbox
  • ✅ Click "Check" to verify connection

Device doesn't vibrate

  • ✅ Click "Test Vibration" to isolate issue
  • ✅ Check device battery level
  • ✅ Verify device is connected in Intiface Central
  • ✅ Try reconnecting device via Bluetooth

AI doesn't output commands

  • ✅ Check Technical Prompt is properly set
  • ✅ Some models need explicit instruction ("use stroke() to vibrate me")
  • ✅ Try Remote Vibrator Mode for pure pattern generation
  • ✅ Small models (<7B) may struggle with command syntax

Graph not updating

  • ✅ Commands need to be executing for graph to show
  • ✅ Refresh browser if frozen
  • ✅ Check browser console for JavaScript errors

Privacy and Security

  • 100% Local: No data leaves your machine
  • No Analytics: Zero tracking or telemetry
  • Open Source: Inspect all code yourself
  • LM Studio: Your conversations stay private
  • Local Network Only: Server binds to 127.0.0.1

⚠️ Warning: Do not expose port 8000 to the internet without adding authentication.


Contributing

This is an open-source project. Contributions welcome:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Test thoroughly
  5. Submit a pull request

Ideas for contributions:

  • Additional device support (e-stim, strokers)
  • Voice control integration
  • Pattern library/marketplace
  • Multi-user support
  • Mobile app
  • VR integration

Disclaimer

This software is intended for adult use only. Use responsibly and consensually. The developers are not responsible for misuse, device damage, or injury. Always use the stop button if uncomfortable. Never exceed safe intensity levels for your specific devices.


Credits

Built with:

Special thanks to the open-source community for making this possible.


Support

  • GitHub Issues: Report bugs or request features
  • Community: (Add Discord/Forum links if available)

Enjoy responsibly!