README with repository metadata
Browse files
README.md
CHANGED
|
@@ -14,170 +14,162 @@ tags:
|
|
| 14 |
|
| 15 |
# Maverick XR Agent for Unity
|
| 16 |
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
> **Status: release candidate (1.0.0-rc.2).** Tested on Windows 11 x64, Unity 2022.3 LTS, NVIDIA RTX
|
| 26 |
-
> 3050 Ti Laptop (4 GB). See [Limitations](#limitations) before building on it.
|
| 27 |
-
|
| 28 |
-
- **11 tools:** grab, release, place, move_by, rotate, set_state, press, highlight, teleport, find_objects,
|
| 29 |
-
ask_clarification.
|
| 30 |
-
- **Understands** synonyms and general words ("the fruit"), colours, spatial references ("the one next to the chair",
|
| 31 |
-
"the second from the left"), "this / that" with the user's gaze, the object in hand ("put it on the shelf"), filler
|
| 32 |
-
words and speech-recognition noise.
|
| 33 |
-
- **Safe by default:**
|
| 34 |
-
- D5b: a call to a tool or a value that does not exist is turned into a refusal before it reaches your scene; an
|
| 35 |
-
unknown object id is generated again under a grammar.
|
| 36 |
-
- Substitute guard: when the user names an object that is only in another room and the model tries to act on a
|
| 37 |
-
different object here, the call is not executed and the model is told where the named object is.
|
| 38 |
-
- **Private and free to run:** llama.cpp on `127.0.0.1`; no account, no cloud call, no per-request cost.
|
| 39 |
|
| 40 |
## Requirements
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
1. **
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
| 75 |
```csharp
|
|
|
|
| 76 |
using SceneAgent;
|
|
|
|
| 77 |
|
| 78 |
-
public class
|
| 79 |
{
|
| 80 |
-
public SceneAgentSession session;
|
| 81 |
|
| 82 |
void Start()
|
| 83 |
{
|
| 84 |
-
session.Line += text => Debug.Log(text);
|
| 85 |
-
session.Finished +=
|
|
|
|
|
|
|
|
|
|
| 86 |
session.world.ToolExecuted += (tool, args, result) =>
|
| 87 |
{
|
| 88 |
-
if (tool == "teleport")
|
| 89 |
};
|
| 90 |
}
|
| 91 |
|
| 92 |
-
|
| 93 |
-
public void
|
|
|
|
|
|
|
|
|
|
| 94 |
|
| 95 |
-
void ShowChoices(
|
| 96 |
-
void
|
| 97 |
}
|
| 98 |
```
|
| 99 |
-
- **Lower level:** `StartCoroutine(agent.Run(text, result => …))` returns an `AgentResult`: the calls, their results,
|
| 100 |
-
the final text or the clarification question, an error, and the time.
|
| 101 |
-
- **Rooms:** give each `SceneItem` a `room`. The model sees the player's room only; it finds objects elsewhere with
|
| 102 |
-
`find_objects` and moves the player with `teleport` (which sets `SceneWorld.playerRoom`; you move the camera in
|
| 103 |
-
`ToolExecuted`).
|
| 104 |
-
- **Gaze:** `SceneAgentGaze` (added by Set Up Scene) sets `SceneWorld.gaze` to the object under the mouse pointer, or at
|
| 105 |
-
the centre of the camera (XR head gaze), so "this / that" resolve. Objects need colliders.
|
| 106 |
-
- **Clarification:** when the agent asks "Which toolbox do you mean?", the user can click a candidate (`session.Answer(id)`)
|
| 107 |
-
or just type "the red one": a short reply while a question is pending answers it; a new command starts over.
|
| 108 |
-
|
| 109 |
-
## What objects can do
|
| 110 |
-
Each label maps to what it affords (can be picked up, is a surface, a container, has on/off or open/closed states, is
|
| 111 |
-
fixed), from the model's catalogue of about 200 everyday object types. For a label the catalogue does not know, tick
|
| 112 |
-
`SceneItem.overrideAffordances` and set the flags, or rename it to a common word; Validate Scene lists every such
|
| 113 |
-
label.
|
| 114 |
|
| 115 |
-
|
| 116 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
|---|---|
|
| 118 |
-
|
|
| 119 |
-
|
|
| 120 |
-
|
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
|
| 147 |
## Limitations
|
| 148 |
-
|
| 149 |
-
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
-
|
| 154 |
-
`ToolExecuted` if
|
| 155 |
-
-
|
| 156 |
-
|
| 157 |
-
- **Room size:** a room of 90 objects worked; 170 exceeded the 4096-token context (a clear error, no crash). Keep rooms
|
| 158 |
-
under about 60 objects for multi-step commands, or raise `contextSize` (more VRAM).
|
| 159 |
-
- **Other languages:** trained on English only. A Turkish command worked in one test; do not rely on it.
|
| 160 |
-
- **Typos** can be read as unknown objects ("lapm").
|
| 161 |
-
- **Infeasible requests (4B):** it sometimes tries the action, Unity refuses it, then it explains.
|
| 162 |
-
- **It sees the scene as data, not the camera.** Keep labels and colours accurate.
|
| 163 |
-
- Not validated for real robots or safety-critical control.
|
| 164 |
-
|
| 165 |
-
Full evaluation: 21 of 22 pre-registered capability targets, 83.6–86.6% on real human instructions (ALFRED-TC, our
|
| 166 |
-
adaptation), 94.5–97.3% on 440 commands through this C# code.
|
| 167 |
|
| 168 |
## Troubleshooting
|
| 169 |
-
|
|
|
|
| 170 |
|---|---|
|
| 171 |
-
| "llama-server not found" |
|
| 172 |
-
| "no model (.gguf) found" |
|
| 173 |
-
| model
|
| 174 |
-
|
|
| 175 |
-
| "the scene and request need N tokens
|
| 176 |
-
| "
|
| 177 |
-
|
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
`Third Party Notices.md`.
|
|
|
|
| 14 |
|
| 15 |
# Maverick XR Agent for Unity
|
| 16 |
|
| 17 |
+
Control a Unity scene with typed or spoken English. This package runs
|
| 18 |
+
[Maverick-4B-Unity-XR-Agent](https://huggingface.co/ErenAta00/Maverick-4B-Unity-XR-Agent-GGUF) on the player's own
|
| 19 |
+
machine through llama.cpp: no account, no internet connection and no API key.
|
| 20 |
+
|
| 21 |
+
You choose which objects the agent may use. For each command the model reads those objects and calls one of 11 tools,
|
| 22 |
+
which Unity then carries out: "put the red mug on the table", "turn on the lamp", "where is the stapler?". When a
|
| 23 |
+
command could mean more than one object, it asks which one. When it cannot do something, it says so.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
## Requirements
|
| 26 |
+
|
| 27 |
+
- Unity 2022.3 LTS or later
|
| 28 |
+
- Windows x64 (Linux and macOS are untested)
|
| 29 |
+
- About 3 GB of free GPU memory. Without a GPU the model runs on the CPU, but slowly.
|
| 30 |
+
- About 3 GB of disk space for the model and llama.cpp
|
| 31 |
+
|
| 32 |
+
## Installation
|
| 33 |
+
|
| 34 |
+
1. In Unity, open **Window > Package Manager**, click **+**, choose **Add package from git URL** and enter:
|
| 35 |
+
|
| 36 |
+
```text
|
| 37 |
+
https://huggingface.co/ErenAta00/Maverick-Unity.git
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
2. Choose **Tools > Scene Agent > Open Model Folder**. This creates `Assets/StreamingAssets/SceneAgent/`.
|
| 41 |
+
3. Copy two things into that folder:
|
| 42 |
+
- **llama.cpp for Windows** from the [llama.cpp releases](https://github.com/ggml-org/llama.cpp/releases): the CUDA 12
|
| 43 |
+
build for NVIDIA GPUs, the Vulkan build for other GPUs, or the CPU build. Copy every file in the archive, not only
|
| 44 |
+
`llama-server.exe`.
|
| 45 |
+
- **The model** `Maverick-4B-Unity-XR-Agent-Q4_K_M.gguf` from the
|
| 46 |
+
[model page](https://huggingface.co/ErenAta00/Maverick-4B-Unity-XR-Agent-GGUF/tree/main).
|
| 47 |
+
|
| 48 |
+
Unity copies `StreamingAssets` into your build, so players do not need to install anything.
|
| 49 |
+
|
| 50 |
+
## Quick start
|
| 51 |
+
|
| 52 |
+
1. Choose **Tools > Scene Agent > Set Up Scene**. This adds a *Scene Agent* object with all components connected,
|
| 53 |
+
including a chat box for testing.
|
| 54 |
+
2. Give your objects plain names, such as *Red Mug*, *Table* or *Floor Lamp*.
|
| 55 |
+
3. Select the objects the agent may use and choose **Tools > Scene Agent > Make Selected Interactive**. Each one gets a
|
| 56 |
+
`SceneItem` with an id (`mug_1`), a label (`mug`), a colour (`red`), a room and the object it stands on.
|
| 57 |
+
4. Choose **Tools > Scene Agent > Validate Scene** and fix anything it reports.
|
| 58 |
+
5. Enter Play mode, type `put the red mug on the table` and press Enter. If the agent asks which mug you mean, click
|
| 59 |
+
one. F1 hides the chat box.
|
| 60 |
+
|
| 61 |
+
## Using it from code
|
| 62 |
+
|
| 63 |
```csharp
|
| 64 |
+
using System.Collections.Generic;
|
| 65 |
using SceneAgent;
|
| 66 |
+
using UnityEngine;
|
| 67 |
|
| 68 |
+
public class VoiceCommands : MonoBehaviour
|
| 69 |
{
|
| 70 |
+
public SceneAgentSession session; // on the Scene Agent object
|
| 71 |
|
| 72 |
void Start()
|
| 73 |
{
|
| 74 |
+
session.Line += text => Debug.Log(text);
|
| 75 |
+
session.Finished += result =>
|
| 76 |
+
{
|
| 77 |
+
if (result.clarificationQuestion != null) ShowChoices(session.Candidates);
|
| 78 |
+
};
|
| 79 |
session.world.ToolExecuted += (tool, args, result) =>
|
| 80 |
{
|
| 81 |
+
if (tool == "teleport") MoveRigTo(session.world.playerRoom);
|
| 82 |
};
|
| 83 |
}
|
| 84 |
|
| 85 |
+
// Typed text or the output of a speech recogniser.
|
| 86 |
+
public void OnCommand(string text) => StartCoroutine(session.Command(text));
|
| 87 |
+
|
| 88 |
+
// The user's answer to "Which one do you mean?".
|
| 89 |
+
public void OnPick(string itemId) => StartCoroutine(session.Answer(itemId));
|
| 90 |
|
| 91 |
+
void ShowChoices(List<string> itemIds) { /* your UI */ }
|
| 92 |
+
void MoveRigTo(string room) { /* your camera rig */ }
|
| 93 |
}
|
| 94 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
|
| 96 |
+
- **Rooms.** Give each `SceneItem` a `room`. The model sees only the player's room. It searches other rooms with
|
| 97 |
+
`find_objects` and moves the player with `teleport`, which sets `SceneWorld.playerRoom`; move your camera rig in
|
| 98 |
+
`ToolExecuted`.
|
| 99 |
+
- **"This" and "that".** `SceneAgentGaze` points them at the object under the mouse, or at the centre of the view in
|
| 100 |
+
XR. The objects need colliders.
|
| 101 |
+
- **Follow-up answers.** When the agent asks which object you mean, the user can pick one (`session.Answer`) or reply
|
| 102 |
+
in words, such as "the red one".
|
| 103 |
+
- **Speech.** Pass the recognised text to `session.Command`. For a fully offline app, use a local recogniser such as
|
| 104 |
+
whisper.cpp.
|
| 105 |
+
|
| 106 |
+
## Tools
|
| 107 |
+
|
| 108 |
+
| Tool | What it does |
|
| 109 |
|---|---|
|
| 110 |
+
| `grab`, `release` | Picks up or drops an object with the left, right or both hands |
|
| 111 |
+
| `place` | Puts an object on a surface or in a container |
|
| 112 |
+
| `move_by`, `rotate` | Moves an object by a given distance or turns it |
|
| 113 |
+
| `set_state` | Switches on or off, opens, closes, locks or unlocks |
|
| 114 |
+
| `press` | Presses a button |
|
| 115 |
+
| `highlight` | Highlights objects |
|
| 116 |
+
| `teleport` | Moves the player to another room |
|
| 117 |
+
| `find_objects` | Searches every room for objects |
|
| 118 |
+
| `ask_clarification` | Asks which object the user means |
|
| 119 |
+
|
| 120 |
+
Unity refuses a call that does not fit the object, such as picking up a table, and tells the model why. What each
|
| 121 |
+
object can do comes from its label and a catalogue of about 200 everyday objects. For a label outside the catalogue,
|
| 122 |
+
turn on `SceneItem.overrideAffordances` and set the flags yourself; **Validate Scene** lists these labels.
|
| 123 |
+
|
| 124 |
+
## Components
|
| 125 |
+
|
| 126 |
+
| Component | Purpose | Main settings |
|
| 127 |
+
|---|---|---|
|
| 128 |
+
| `SceneWorld` | Describes the scene to the model and carries out the tools | `rooms`, `playerRoom`, `ToolExecuted` |
|
| 129 |
+
| `SceneItem` | Marks an object the agent may use | `itemId`, `label`, `color`, `room`, `overrideAffordances` |
|
| 130 |
+
| `SceneAgent` | Sends commands to the model and runs its tool calls | `maxTurns`, `fallbackDecoding`, `guardSubstitutes` |
|
| 131 |
+
| `LocalModelServer` | Starts and stops llama.cpp with the game | `modelPath`, `contextSize`, `preferGpu`, `capFrameRate` |
|
| 132 |
+
| `SceneAgentSession` | Holds one conversation, including follow-up questions | `logDirectory` |
|
| 133 |
+
| `SceneAgentGaze` | Resolves "this" and "that" | |
|
| 134 |
+
| `SceneAgentChatBox` | On-screen chat for testing | `toggleKey`, `visibleLines` |
|
| 135 |
+
| `SceneAgentScriptRunner` | Plays a text file of commands and writes a report | `script`, `outputDirectory` |
|
| 136 |
+
|
| 137 |
+
`fallbackDecoding` checks every answer before it reaches your scene: a call to a tool or value that does not exist is
|
| 138 |
+
turned into a refusal. `guardSubstitutes` stops the model from acting on a similar object when the one the user named
|
| 139 |
+
is in another room. Leave both on.
|
| 140 |
+
|
| 141 |
+
## Performance
|
| 142 |
+
|
| 143 |
+
- **Cap the frame rate.** An uncapped renderer on the same GPU can make the model several times slower.
|
| 144 |
+
`LocalModelServer` caps rendering at 30 frames per second while the model runs on the GPU. In XR, set `capFrameRate`
|
| 145 |
+
to 0 and let the headset set the frame rate.
|
| 146 |
+
- **Keep rooms small.** Under about 60 interactive objects per room, multi-step commands fit the default 4,096-token
|
| 147 |
+
context. For larger rooms, raise `LocalModelServer.contextSize`, which needs more GPU memory.
|
| 148 |
|
| 149 |
## Limitations
|
| 150 |
+
|
| 151 |
+
- English only, and only the 11 tools. The agent cannot create or delete objects or change materials, lighting or
|
| 152 |
+
physics.
|
| 153 |
+
- It finds and fetches objects in other rooms ("bring me the book"), but when the lamp is in another room, "turn on
|
| 154 |
+
the lamp" gets "there is no lamp here". The user should name the room or go there first.
|
| 155 |
+
- Placed objects go to the centre of the target, so two objects placed on the same shelf overlap. Arrange them in
|
| 156 |
+
`ToolExecuted` if this matters in your scene.
|
| 157 |
+
- The model reads the scene as data, not through the camera. Keep object names and colours accurate.
|
| 158 |
+
- Not intended for robots or safety-critical control.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
|
| 160 |
## Troubleshooting
|
| 161 |
+
|
| 162 |
+
| Problem | Fix |
|
| 163 |
|---|---|
|
| 164 |
+
| "llama-server not found" | Copy every file of the llama.cpp release into the model folder. |
|
| 165 |
+
| "no model (.gguf) found" | Put the `.gguf` file in the model folder, or set `LocalModelServer.modelPath`. |
|
| 166 |
+
| The model runs on the CPU | The llama.cpp build does not match your GPU, or GPU memory is full. See the log at `LocalModelServer.LogPath`. |
|
| 167 |
+
| Every answer is slow | Cap the frame rate and check the GPU temperature. |
|
| 168 |
+
| "the scene and request need N tokens" | The room has too many objects. Split it or raise `LocalModelServer.contextSize`. |
|
| 169 |
+
| "object ... is not visible" | The object's `room` is not `SceneWorld.playerRoom`. |
|
| 170 |
+
| A call on your object is refused | Its label is not in the catalogue. Use `overrideAffordances` or a more common name. |
|
| 171 |
+
|
| 172 |
+
## Licence
|
| 173 |
+
|
| 174 |
+
The package is released under the [MIT License](LICENSE.md). The model is released under Apache-2.0, like its base
|
| 175 |
+
model, Qwen3-4B. llama.cpp is released under the MIT License.
|
|
|