GhostLLM: Creating the DBus server with Ollama integration
Table of contents
Hello,
This is part two of my GhostLLM project. This project is about integrating “Rewrite Text” functionality natively into GTK3 widgets. Check the part one post if you missed it.
In this part, I will going over the DBus server code (written in Python) which will be exposing DBus interface on the Session Bus with a method “RewriteText” which accepts user input (String) and returns the rewritten sentence as the output.
Implementation
The code for this project lives on GitHub here.
The main part here is to setup DBus interface. I used dbus-fast
to simplify this.
# File: server.py
# DBus interface is declared here
# The `_` prefix is to indicate this is an internal class.
class _GhostLLMDBusInterface(ServiceInterface):
def __init__(self):
super().__init__(DBUS_ADDRESS_NAME)
self.ollama = OllamaController()
@method()
def RewriteText(self, input_text: 's') -> 's':
return self.ollama.chat(input_text)
# Wrapper class that simplifies executing this code from `__main__.py`
class GhostLLMDBus():
async def init(self):
# Connect to Session Bus
bus = await MessageBus(bus_type=BusType.SESSION).connect()
# Implement the DBus interface
interface = _GhostLLMDBusInterface()
bus.export(DBUS_INTERFACE_NAME, interface)
await bus.request_name(DBUS_ADDRESS_NAME)
print(f"DBUS Service initialized at {DBUS_INTERFACE_NAME}")
await bus.wait_for_disconnect()
# We call this in `__main__.py` that will kick things off!
def listen(self):
asyncio.run(self.init())
# File: ollama.py
from ollama import generate
from ollama import GenerateResponse
from .constants import OLLAMA_MODEL_NAME, OLLAMA_SYSTEM_PROMPT
class OllamaController():
def chat(self, input_str: str) -> str:
response: GenerateResponse = generate(
model=OLLAMA_MODEL_NAME, # qwen2.5:3b
system=OLLAMA_SYSTEM_PROMPT,
stream=False,
prompt= f'rewrite "{input_str}"'
)
return response.response
This code is pretty straight-forward. I used the usage code from Ollama Python library. I use /generate
endpoint to customize the prompt to fit the needs. The constants here could be replaced with a config file for easier access.
You should always use ‘system’ role to set your instructions. This way, your users wouldn’t be able to change or override your instructions. That’s called a prompt injection attack. Learn more about it on Wikipedia.
__main__.py:
import sys
from .server import GhostLLMDBus
if __name__ == '__main__':
try:
gh = GhostLLMDBus()
gh.listen()
except KeyboardInterrupt:
sys.exit(0)
I tried this code with LLAMA3.2 model but it didn’t respect the system prompt. It always tried to process the user prompt rather than simply rewriting the text. Hence, I went with qwen2.5:3b model with the following prompt:
// SYSTEM PROMPT:
Your work is to rewrite sentences to make them more professional. Reply with 1 rewritten sentence. do not say anything else.
// USER PROMPT:
rewrite "xxx"
You run the project using:
$ cd <project-root> # like cd ~/Projects/ghostllm-dbus
# You need to run `pip install -r requirements.txt` first!!
$ python -m ghostllm-dbus
Screenshot
I used QTDBusViewer software to test the server. You can use any other software :)
Input prompt:
Response:
Next Steps
The next part is going to be difficult. I need to figure out C code that will interact with DBus instance and present it to the user.
I will also need to figure out a way to replace the selected text in buffer with GhostLLM’s response.
Conclusion
Thanks for reading! I would appreciate if you could leave a Like to this post.
Please leave a comment if you think I missed something :)
Bye for now :-)