Skip to content

Latest commit

 

History

History
344 lines (254 loc) · 6.61 KB

en-README.md

File metadata and controls

344 lines (254 loc) · 6.61 KB

COMPLETE AI BOT FOR OPENSIMULATOR IN PYTHON


🧠 FINAL BOT OVERVIEW

The bot will be able to:

  • ✅ Log into OpenSimulator as an avatar
  • ✅ Walk, turn, move around
  • ✅ Know where it is and which objects surround it
  • ✅ Listen and respond in chat
  • ✅ Use LLM + local RAG
  • ✅ Show explanatory subtitles (sources + reasoning)

📁 FINAL PROJECT STRUCTURE

opensim_ai_bot/
│
├─ lib/
│  └─ OpenMetaverse.dll
│
├─ bot/
│  ├─ client.py        # connection + events
│  ├─ movement.py      # walk, turn
│  ├─ perception.py    # position, objects
│
├─ ai/
│  ├─ llm.py           # LLM
│  ├─ rag.py           # local RAG
│  └─ prompts.py
│
├─ knowledge/
│  ├─ docs/
│  │  ├─ opensim.txt
│  │  ├─ world.md
│  │  └─ objects.md
│
├─ subtitles/
│  └─ explain.py       # explanatory subtitles
│
├─ main.py
└─ requirements.txt

1️⃣ BOT MOVEMENT (walk, turn)

📄 bot/movement.py

import time
from OpenMetaverse import Vector3

class BotMovement:
    def __init__(self, client):
        self.client = client

    def walk_forward(self, meters=2.0):
        pos = self.client.Self.SimPosition
        direction = self.client.Self.Movement.BodyRotation.GetForwardVector()

        new_pos = Vector3(
            pos.X + direction.X * meters,
            pos.Y + direction.Y * meters,
            pos.Z
        )

        self.client.Self.AutoPilot(new_pos)
        time.sleep(2)

    def turn_left(self):
        self.client.Self.Movement.TurnLeft(True)
        time.sleep(1)
        self.client.Self.Movement.TurnLeft(False)

    def turn_right(self):
        self.client.Self.Movement.TurnRight(True)
        time.sleep(1)
        self.client.Self.Movement.TurnRight(False)

2️⃣ WORLD PERCEPTION (position + objects)

📄 bot/perception.py

class BotPerception:
    def __init__(self, client):
        self.client = client

    def get_position(self):
        pos = self.client.Self.SimPosition
        return f"X={pos.X:.1f}, Y={pos.Y:.1f}, Z={pos.Z:.1f}"

    def list_nearby_objects(self, radius=10):
        objects = []
        for obj in self.client.Network.CurrentSim.ObjectsPrimitives.Values:
            if obj.Properties and obj.Properties.Name:
                objects.append(obj.Properties.Name)
        return objects[:10]

3️⃣ CONNECTING THE LLM (local or API)

Here I use abstraction, so you can swap it later.

📄 ai/llm.py

class LLM:
    def generate(self, prompt):
        # Placeholder (later you connect a real model)
        return f"(Response generated by the LLM)\n{prompt[:200]}"

4️⃣ LOCAL RAG (simple and effective)

📄 ai/rag.py

import os

class RAG:
    def __init__(self, docs_path="knowledge/docs"):
        self.docs = {}
        self.load_docs(docs_path)

    def load_docs(self, path):
        for file in os.listdir(path):
            if file.endswith(".txt") or file.endswith(".md"):
                with open(os.path.join(path, file), "r", encoding="utf-8") as f:
                    self.docs[file] = f.read()

    def retrieve(self, query):
        for name, text in self.docs.items():
            if query.lower() in text.lower():
                return name, text[:500]
        return None, "No relevant information."

5️⃣ EXPLANATORY SUBTITLES (transparent RAG)

📄 subtitles/explain.py

def explain(source, reason):
    return f"""
📚 Source:
{source}

🧠 Explanation:
{reason}
"""

🧩 MAIN BOT CLIENT

📄 bot/client.py

import clr
import time

clr.AddReference("lib/OpenMetaverse")

from OpenMetaverse import GridClient
from bot.movement import BotMovement
from bot.perception import BotPerception
from ai.llm import LLM
from ai.rag import RAG
from subtitles.explain import explain

class OpenSimBot:
    def __init__(self, first, last, password, uri):
        self.client = GridClient()

        self.first = first
        self.last = last
        self.password = password
        self.uri = uri

        self.movement = BotMovement(self.client)
        self.perception = BotPerception(self.client)
        self.llm = LLM()
        self.rag = RAG()

        self.client.Self.ChatFromSimulator += self.on_chat

    def login(self):
        params = self.client.Network.DefaultLoginParams(
            self.first,
            self.last,
            self.password,
            "AI Bot",
            "Python"
        )
        params.URI = self.uri

        print("🔌 Connecting...")
        if not self.client.Network.Login(params):
            raise SystemExit("❌ Login failed")

        print("✅ Bot connected!")

    def on_chat(self, sender, args):
        msg = args.Message.lower()
        name = args.FromName

        print(f"💬 {name}: {msg}")

        if "walk" in msg:
            self.movement.walk_forward()
            self.say("🚶 Walking")

        elif "where are you" in msg:
            pos = self.perception.get_position()
            self.say(f"📍 I am at {pos}")

        elif "what do you see" in msg:
            objs = self.perception.list_nearby_objects()
            self.say("👀 I see: " + ", ".join(objs))

        else:
            source, context = self.rag.retrieve(msg)
            answer = self.llm.generate(context)

            legend = explain(
                source,
                "I used internal world documentation to answer."
            )

            self.say(answer)
            self.say(legend)

    def say(self, text):
        self.client.Self.Chat(
            text,
            0,
            self.client.Self.ChatType.Normal
        )

    def run(self):
        print("🤖 Bot active")
        while True:
            time.sleep(1)

🚀 MAIN

📄 main.py

from bot.client import OpenSimBot

bot = OpenSimBot(
    first="AI",
    last="Bot",
    password="password",
    uri="http://127.0.0.1:9000"
)

bot.login()
bot.run()

🧪 OPENSIM EXAMPLE

User:

where are you?

Bot:

📍 I am at X=128.0, Y=128.0, Z=22.0

User:

what is this object?

Bot:

(Response generated by the LLM)
This object is part of the system...

📚 Source:
objects.md

🏁 YOU NOW HAVE

  • ✅ Complete AI bot
  • ✅ Real movement
  • ✅ World perception
  • ✅ Local RAG
  • ✅ LLM ready
  • ✅ Explanatory subtitles
  • ✅ Professional structure

🔥 NEXT UPGRADES

  • FAISS / embeddings
  • Per-user memory
  • HUD with subtitles
  • Menu-based commands
  • Multilingual support
  • XML / JSON logs
  • Teacher / guide / safety mode