Zum Inhalt

Modul 6: Chatbot

KI ist in aller Munde! Und so braucht auch unsere Smart City einen KI-Assistenten. Du kannst dich mit diesem unterhalten, Infos aus der Stadt abfragen und die Stadt auch beeinflussen.

Vorbereitung

Zur Durchführung benötigst du einen Editor. Wir verwenden Visual Studio Code:

Der Editor glieder sich grob in zwei Bereiche: links die Dateiliste und rechts das Editorfenster. Rechts-klicke nun links in die Dateiliste, um eine neue Datei zu erstellen. Nenne sie.main.py und fülle sie im Editorfenster rechts mit Inhalt:

print("Hallo")

Wenn du auf kleine Dreieck oben rechts klickst, wird dein Programm gestartet. Du siehst dann die Ausgabe Hallo unten im Terminal.

Verbinde dich nun mit dem MQTT-Broker:

import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
    print("Verbunden!")
    client.subscribe("#")

def on_message(client, userdata, msg):
    print(f"{msg.topic}: {msg.payload.decode()}")

mqtt_client = mqtt.Client()
mqtt_client.on_connect = on_connect
mqtt_client.on_message = on_message

mqtt_client.connect("imiq-lab.et.uni-magdeburg.de", 21883)
mqtt_client.loop_forever()

Überprüfe mithilfe des MQTT Viewer, ob du Nachrichten empfangen kannst.

Info

Warte nun, bis alle Teilnehmenden sich mit dem Broker verbunden haben.

Lokale LLMs

Mit Ollama kannst du LLMs lokal installieren und ausprobieren:

Chatte ein wenig mit einem lokalen LLM, um ein Gefühl für die Schnelligkeit / Fähigkeiten zu bekommen. Wir werden qwen3:1.7b verwenden, du kannst aber auch andere LLMs herunterladen. Unter https://ollama.com/library findest du eine Liste.

Du kannst nun dein lokales LLM auch programmatisch ansprechen. Füge dafür folgenden Code in den Editor ein:

from openai import OpenAI

llm_client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama",
)

prompt = input("> ")
response = llm_client.chat.completions.create(
    model="qwen3:1.7b",
    messages=[
        {
            "role": "user",
            "content": prompt
        }
    ],
    extra_body={"think": False},
)
answer = response.choices[0].message
print(f"< {answer.content}")
Gibt deine Frage ein und drücke Enter, um die Antwort zu erhalten.

Statt einmalig eine Frage zu stellen, können wir auch einen Chat erstellen. Dafür merken wir uns den Chatverlauf (messages.append) und übergeben ihn an das LLM:

from openai import OpenAI

llm_client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama",
)

print("(Strg+C zum Beenden)")

messages = []

while True:
    prompt = input("> ")

    messages.append({
        "role": "user",
        "content": prompt,
    })

    response = llm_client.chat.completions.create(
        model="qwen3:1.7b",
        messages=messages,
        extra_body={"think": False},
    )

    answer = response.choices[0].message

    print(f"< {answer.content}")

    messages.append({
        "role": "assistant",
        "content": answer.content,
    })
Du kannst den Chat mit Strg+C abbrechen.

Zugriff auf die Smart City

Nun wollen wir dem Chatbot Zugriff auf unsere Stadt geben, d.h. den MQTT-Broker. Dafür übergeben wir dem LLM sogenannte Tools:

from openai import OpenAI
import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, rc):
    client.subscribe("#")

temperature = ""
rain = ""
def on_message(client, userdata, msg):
    topic = msg.topic
    payload = msg.payload.decode()
    if topic == "city/weather/temperature":
        global temperature
        temperature = payload
    elif topic == "city/weather/rain":
        global rain
        rain = payload

mqtt_client = mqtt.Client()
mqtt_client.on_connect = on_connect
mqtt_client.on_message = on_message
mqtt_client.connect("imiq-lab.et.uni-magdeburg.de", 21883)
mqtt_client.loop_start()

llm_client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama",
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Returns the current weather"
        },
    }
]

messages = []

while True:
    prompt = input("> ")

    messages.append({
        "role": "user",
        "content": prompt,
    })

    while True:
        response = llm_client.chat.completions.create(
            model="qwen3:1.7b",
            messages=messages,
            tools=tools,
            extra_body={"think": False},
        )

        answer = response.choices[0].message

        if not answer.tool_calls:
            print(f"< {answer.content}")
            messages.append({
                "role": "assistant",
                "content": answer.content,
            })
            break

        messages.append(answer)
        for tool_call in answer.tool_calls:
            name = tool_call.function.name
            if name == "get_weather":
                result = f"Temperature: {temperature}°C, rain: {rain}%"
            else:
                raise Exception(f"Unknown tool {name}")
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": result,
            })

Deine Aufgabe

Erstelle nun weitere Tools. Am besten stimmst du dich dafür mit den anderen Teilnehmenden ab.

In Modul 2 wird ein Parkplatzsensor ausgelesen und unter dem Topic city/parking/1 bzw. city/parkin/2 bereitgestellt.

In Modul 4 wird eine Ampelsteuerung programmiert, die man mit dem Topic city/traffic_light/emergency beeinflussen kann.

In Modul 5 werden die Laternen eingeschaltet, um einen bestimmen Weg zu visualisieren. Du kannst dafür ein bestimmtes Ziel nach city/routing/destination senden.