diff --git a/.github/doxygen/Doxyfile b/.github/doxygen/Doxyfile
index a1c207e3..de17f930 100644
--- a/.github/doxygen/Doxyfile
+++ b/.github/doxygen/Doxyfile
@@ -951,6 +951,7 @@ WARN_LOGFILE           =
 
 INPUT                  = README.md \
                          Runtime \
+                         Runtime/RAG \
                          .github \
                          LICENSE.md \
                          "Third Party Notices.md"
diff --git a/Editor/LLMCallerEditor.cs b/Editor/LLMCallerEditor.cs
new file mode 100644
index 00000000..1a20172e
--- /dev/null
+++ b/Editor/LLMCallerEditor.cs
@@ -0,0 +1,47 @@
+using System;
+using UnityEditor;
+using UnityEngine;
+using System.Collections.Generic;
+
+namespace LLMUnity
+{
+    [CustomEditor(typeof(LLMCaller), true)]
+    public class LLMCallerEditor : PropertyEditor {}
+
+    [CustomEditor(typeof(LLMCharacter), true)]
+    public class LLMCharacterEditor : LLMCallerEditor
+    {
+        public override void AddModelSettings(SerializedObject llmScriptSO)
+        {
+            if (!llmScriptSO.FindProperty("advancedOptions").boolValue)
+            {
+                base.AddModelSettings(llmScriptSO);
+            }
+            else
+            {
+                EditorGUILayout.LabelField("Model Settings", EditorStyles.boldLabel);
+                ShowPropertiesOfClass("", llmScriptSO, new List<Type> { typeof(ModelAttribute) }, false);
+
+                EditorGUILayout.BeginHorizontal();
+                GUILayout.Label("Grammar", GUILayout.Width(EditorGUIUtility.labelWidth));
+                if (GUILayout.Button("Load grammar", GUILayout.Width(buttonWidth)))
+                {
+                    EditorApplication.delayCall += () =>
+                    {
+                        string path = EditorUtility.OpenFilePanelWithFilters("Select a gbnf grammar file", "", new string[] { "Grammar Files", "gbnf" });
+                        if (!string.IsNullOrEmpty(path))
+                        {
+                            ((LLMCharacter)target).SetGrammar(path);
+                        }
+                    };
+                }
+                EditorGUILayout.EndHorizontal();
+
+                ShowPropertiesOfClass("", llmScriptSO, new List<Type> { typeof(ModelAdvancedAttribute) }, false);
+            }
+        }
+    }
+
+    [CustomEditor(typeof(DBSearch), true)]
+    public class DBSearchEditor : PropertyEditor {}
+}
diff --git a/Editor/LLMCharacterEditor.cs.meta b/Editor/LLMCallerEditor.cs.meta
similarity index 100%
rename from Editor/LLMCharacterEditor.cs.meta
rename to Editor/LLMCallerEditor.cs.meta
diff --git a/Editor/LLMCharacterEditor.cs b/Editor/LLMCharacterEditor.cs
deleted file mode 100644
index 0111dcb4..00000000
--- a/Editor/LLMCharacterEditor.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-using UnityEditor;
-using UnityEngine;
-using System.Collections.Generic;
-
-namespace LLMUnity
-{
-    [CustomEditor(typeof(LLMCharacter), true)]
-    public class LLMCharacterEditor : PropertyEditor
-    {
-        protected override Type[] GetPropertyTypes()
-        {
-            return new Type[] { typeof(LLMCharacter) };
-        }
-
-        public void AddModelSettings(SerializedObject llmScriptSO, LLMCharacter llmCharacterScript)
-        {
-            EditorGUILayout.LabelField("Model Settings", EditorStyles.boldLabel);
-            ShowPropertiesOfClass("", llmScriptSO, new List<Type> { typeof(ModelAttribute) }, false);
-
-            if (llmScriptSO.FindProperty("advancedOptions").boolValue)
-            {
-                EditorGUILayout.BeginHorizontal();
-                GUILayout.Label("Grammar", GUILayout.Width(EditorGUIUtility.labelWidth));
-                if (GUILayout.Button("Load grammar", GUILayout.Width(buttonWidth)))
-                {
-                    EditorApplication.delayCall += () =>
-                    {
-                        string path = EditorUtility.OpenFilePanelWithFilters("Select a gbnf grammar file", "", new string[] { "Grammar Files", "gbnf" });
-                        if (!string.IsNullOrEmpty(path))
-                        {
-                            llmCharacterScript.SetGrammar(path);
-                        }
-                    };
-                }
-                EditorGUILayout.EndHorizontal();
-
-                ShowPropertiesOfClass("", llmScriptSO, new List<Type> { typeof(ModelAdvancedAttribute) }, false);
-            }
-        }
-
-        public override void OnInspectorGUI()
-        {
-            LLMCharacter llmScript = (LLMCharacter)target;
-            SerializedObject llmScriptSO = new SerializedObject(llmScript);
-
-            OnInspectorGUIStart(llmScriptSO);
-            AddOptionsToggles(llmScriptSO);
-
-            AddSetupSettings(llmScriptSO);
-            AddChatSettings(llmScriptSO);
-            Space();
-            AddModelSettings(llmScriptSO, llmScript);
-
-            OnInspectorGUIEnd(llmScriptSO);
-        }
-    }
-
-    [CustomEditor(typeof(LLMClient))]
-    public class LLMClientEditor : LLMCharacterEditor {}
-}
diff --git a/Editor/LLMEditor.cs b/Editor/LLMEditor.cs
index 76444a71..5ed29afe 100644
--- a/Editor/LLMEditor.cs
+++ b/Editor/LLMEditor.cs
@@ -30,11 +30,6 @@ public class LLMEditor : PropertyEditor
         bool customURLFocus = false;
         bool expandedView = false;
 
-        protected override Type[] GetPropertyTypes()
-        {
-            return new Type[] { typeof(LLM) };
-        }
-
         public void AddSecuritySettings(SerializedObject llmScriptSO, LLM llmScript)
         {
             void AddSSLLoad(string type, Callback<string> setterCallback)
@@ -110,7 +105,7 @@ public void AddModelLoaders(SerializedObject llmScriptSO, LLM llmScript)
             if (downloadOnStart != LLMManager.downloadOnStart) LLMManager.SetDownloadOnStart(downloadOnStart);
         }
 
-        public void AddModelSettings(SerializedObject llmScriptSO)
+        public override void AddModelSettings(SerializedObject llmScriptSO)
         {
             List<Type> attributeClasses = new List<Type> { typeof(ModelAttribute) };
             if (llmScriptSO.FindProperty("advancedOptions").boolValue)
@@ -450,6 +445,22 @@ private void CopyToClipboard(string text)
             te.Copy();
         }
 
+        public void AddExtrasToggle()
+        {
+            if (ToggleButton("Use extras", LLMUnitySetup.FullLlamaLib)) LLMUnitySetup.SetFullLlamaLib(!LLMUnitySetup.FullLlamaLib);
+        }
+
+        public override void AddOptionsToggles(SerializedObject llmScriptSO)
+        {
+            AddDebugModeToggle();
+
+            EditorGUILayout.BeginHorizontal();
+            AddAdvancedOptionsToggle(llmScriptSO);
+            AddExtrasToggle();
+            EditorGUILayout.EndHorizontal();
+            Space();
+        }
+
         public override void OnInspectorGUI()
         {
             if (elementFocus != "")
diff --git a/Editor/PropertyEditor.cs b/Editor/PropertyEditor.cs
index 9b4d7433..31a727a9 100644
--- a/Editor/PropertyEditor.cs
+++ b/Editor/PropertyEditor.cs
@@ -10,23 +10,24 @@ public class PropertyEditor : Editor
     {
         public static int buttonWidth = 150;
 
-        public void AddScript(SerializedObject llmScriptSO)
+        public virtual void AddScript(SerializedObject llmScriptSO)
         {
             var scriptProp = llmScriptSO.FindProperty("m_Script");
             EditorGUILayout.PropertyField(scriptProp);
         }
 
-        public bool ToggleButton(string text, bool activated)
+        public virtual bool ToggleButton(string text, bool activated)
         {
             GUIStyle style = new GUIStyle("Button");
             if (activated) style.normal = new GUIStyleState() { background = Texture2D.grayTexture };
             return GUILayout.Button(text, style, GUILayout.Width(buttonWidth));
         }
 
-        public void AddSetupSettings(SerializedObject llmScriptSO)
+        public virtual void AddSetupSettings(SerializedObject llmScriptSO)
         {
             List<Type> attributeClasses = new List<Type>(){typeof(LocalRemoteAttribute)};
-            attributeClasses.Add(llmScriptSO.FindProperty("remote").boolValue ? typeof(RemoteAttribute) : typeof(LocalAttribute));
+            SerializedProperty remoteProperty = llmScriptSO.FindProperty("remote");
+            if (remoteProperty != null) attributeClasses.Add(remoteProperty.boolValue ? typeof(RemoteAttribute) : typeof(LocalAttribute));
             attributeClasses.Add(typeof(LLMAttribute));
             if (llmScriptSO.FindProperty("advancedOptions").boolValue)
             {
@@ -35,37 +36,64 @@ public void AddSetupSettings(SerializedObject llmScriptSO)
             ShowPropertiesOfClass("Setup Settings", llmScriptSO, attributeClasses, true);
         }
 
-        public void AddChatSettings(SerializedObject llmScriptSO)
+        public virtual void AddModelSettings(SerializedObject llmScriptSO)
+        {
+            List<Type> attributeClasses = new List<Type>(){typeof(ModelAttribute)};
+            if (llmScriptSO.FindProperty("advancedOptions").boolValue)
+            {
+                attributeClasses.Add(typeof(ModelAdvancedAttribute));
+            }
+            ShowPropertiesOfClass("Model Settings", llmScriptSO, attributeClasses, true);
+        }
+
+        public virtual void AddChatSettings(SerializedObject llmScriptSO)
         {
             List<Type> attributeClasses = new List<Type>(){typeof(ChatAttribute)};
             if (llmScriptSO.FindProperty("advancedOptions").boolValue)
             {
                 attributeClasses.Add(typeof(ChatAdvancedAttribute));
             }
-            ShowPropertiesOfClass("Chat Settings", llmScriptSO, attributeClasses, false);
+            ShowPropertiesOfClass("Chat Settings", llmScriptSO, attributeClasses, true);
         }
 
-        public void AddOptionsToggles(SerializedObject llmScriptSO)
+        public void AddDebugModeToggle()
         {
             LLMUnitySetup.SetDebugMode((LLMUnitySetup.DebugModeType)EditorGUILayout.EnumPopup("Log Level", LLMUnitySetup.DebugMode));
+        }
+
+        public void AddAdvancedOptionsToggle(SerializedObject llmScriptSO)
+        {
+            List<SerializedProperty> properties = GetPropertiesOfClass(llmScriptSO, new List<Type>(){typeof(AdvancedAttribute)});
+            if (properties.Count == 0) return;
 
-            EditorGUILayout.BeginHorizontal();
             SerializedProperty advancedOptionsProp = llmScriptSO.FindProperty("advancedOptions");
             string toggleText = (advancedOptionsProp.boolValue ? "Hide" : "Show") + " Advanced Options";
             if (ToggleButton(toggleText, advancedOptionsProp.boolValue)) advancedOptionsProp.boolValue = !advancedOptionsProp.boolValue;
-            if (ToggleButton("Use extras", LLMUnitySetup.FullLlamaLib)) LLMUnitySetup.SetFullLlamaLib(!LLMUnitySetup.FullLlamaLib);
-            EditorGUILayout.EndHorizontal();
+        }
+
+        public virtual void AddOptionsToggles(SerializedObject llmScriptSO)
+        {
+            AddAdvancedOptionsToggle(llmScriptSO);
             Space();
         }
 
-        public void Space()
+        public virtual void Space()
         {
             EditorGUILayout.Space((int)EditorGUIUtility.singleLineHeight / 2);
         }
 
         protected virtual Type[] GetPropertyTypes()
         {
-            return new Type[] {};
+            List<Type> types = new List<Type>();
+            Type currentType = target.GetType();
+            while (currentType != null)
+            {
+                types.Add(currentType);
+                currentType = currentType.BaseType;
+                if (currentType == typeof(MonoBehaviour)) break;
+            }
+            types.Reverse();
+            return types.ToArray();
         }
 
         public List<SerializedProperty> GetPropertiesOfClass(SerializedObject so, List<Type> attributeClasses)
@@ -92,7 +120,7 @@ public List<SerializedProperty> GetPropertiesOfClass(SerializedObject so, List<T
             return properties;
         }
 
-        public void ShowPropertiesOfClass(string title, SerializedObject so, List<Type> attributeClasses, bool addSpace = true, List<Type> excludeAttributeClasses = null)
+        public bool ShowPropertiesOfClass(string title, SerializedObject so, List<Type> attributeClasses, bool addSpace = true, List<Type> excludeAttributeClasses = null)
         {
             // display a property if it belongs to a certain class and/or has a specific attribute class
             List<SerializedProperty> properties = GetPropertiesOfClass(so, attributeClasses);
@@ -109,7 +137,7 @@ public void ShowPropertiesOfClass(string title, SerializedObject so, List<Type>
                 }
                 foreach (SerializedProperty prop in removeProperties) properties.Remove(prop);
             }
-            if (properties.Count == 0) return;
+            if (properties.Count == 0) return false;
             if (title != "") EditorGUILayout.LabelField(title, EditorStyles.boldLabel);
             foreach (SerializedProperty prop in properties)
             {
@@ -148,6 +176,7 @@ public void ShowPropertiesOfClass(string title, SerializedObject so, List<Type>
                 }
             }
             if (addSpace) Space();
+            return true;
         }
 
         public bool PropertyInClass(SerializedProperty prop, Type targetClass, Type attributeClass = null)
@@ -181,7 +210,7 @@ public Attribute GetPropertyAttribute(SerializedProperty prop, Type attributeCla
             return null;
         }
 
-        public void OnInspectorGUIStart(SerializedObject scriptSO)
+        public virtual void OnInspectorGUIStart(SerializedObject scriptSO)
         {
             scriptSO.Update();
             GUI.enabled = false;
@@ -190,12 +219,26 @@ public void OnInspectorGUIStart(SerializedObject scriptSO)
             EditorGUI.BeginChangeCheck();
         }
 
-        public void OnInspectorGUIEnd(SerializedObject scriptSO)
+        public virtual void OnInspectorGUIEnd(SerializedObject scriptSO)
         {
             if (EditorGUI.EndChangeCheck())
                 Repaint();
 
             scriptSO.ApplyModifiedProperties();
         }
+
+        public override void OnInspectorGUI()
+        {
+            SerializedObject llmScriptSO = new SerializedObject(target);
+
+            OnInspectorGUIStart(llmScriptSO);
+            AddOptionsToggles(llmScriptSO);
+
+            AddSetupSettings(llmScriptSO);
+            AddChatSettings(llmScriptSO);
+            AddModelSettings(llmScriptSO);
+
+            OnInspectorGUIEnd(llmScriptSO);
+        }
     }
 }
diff --git a/README.md b/README.md
index 984c6dd2..e2f9c453 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,8 @@
 
 LLM for Unity enables seamless integration of Large Language Models (LLMs) within the Unity engine.<br>
 It allows to create intelligent characters that your players can interact with for an immersive experience.<br>
-LLM for Unity is built on top of the awesome [llama.cpp](https://github.com/ggerganov/llama.cpp) and [llamafile](https://github.com/Mozilla-Ocho/llamafile) libraries.
+The package also features a Retrieval-Augmented Generation (RAG) system that allows to performs semantic search across your data, which can be used to enhance the character's knowledge.
+LLM for Unity is built on top of the awesome [llama.cpp](https://github.com/ggerganov/llama.cpp) library.
 
 <sub>
 <a href="#at-a-glance" style="color: black">At a glance</a>&nbsp;&nbsp;•&nbsp;
@@ -27,15 +28,16 @@ LLM for Unity is built on top of the awesome [llama.cpp](https://github.com/gger
 <a href="#games-using-llm-for-unity" style=color: black>Games using LLM for Unity</a>&nbsp;&nbsp;•&nbsp;
 <a href="#setup" style=color: black>Setup</a>&nbsp;&nbsp;•&nbsp;
 <a href="#how-to-use" style=color: black>How to use</a>&nbsp;&nbsp;•&nbsp;
-<a href="#examples" style=color: black>Examples</a>&nbsp;&nbsp;•&nbsp;
+<a href="#semantic-search-with-a-retrieval-augmented-generation-(rag)-system" style=color: black>RAG</a>&nbsp;&nbsp;•&nbsp;
 <a href="#llm-model-management" style=color: black>LLM model management</a>&nbsp;&nbsp;•&nbsp;
+<a href="#examples" style=color: black>Examples</a>&nbsp;&nbsp;•&nbsp;
 <a href="#options" style=color: black>Options</a>&nbsp;&nbsp;•&nbsp;
 <a href="#license" style=color: black>License</a>
 </sub>
 
 ## At a glance
 - 💻 Cross-platform! Windows, Linux, macOS and Android
-- 🏠 Runs locally without internet access. No data ever leaves the game!
+- 🏠 Runs locally without internet access. No data ever leave the game!
 - ⚡ Blazing fast inference on CPU and GPU (Nvidia, AMD, Apple Metal)
 - 🤗 Supports all major LLM models
 - 🔧 Easy to setup, call with a single line of code
@@ -58,7 +60,6 @@ LLM for Unity is built on top of the awesome [llama.cpp](https://github.com/gger
 - [Murder in Aisle 4](https://roadedlich.itch.io/murder-in-aisle-4)
 - [Finicky Food Delivery AI](https://helixngc7293.itch.io/finicky-food-delivery-ai)
 - [AI Emotional Girlfriend](https://whynames.itch.io/aiemotionalgirlfriend)
-- [AI Speak](https://jdscogin.wixsite.com/aispeak)
 - [Case Closed](https://store.steampowered.com/app/2532160/Case_Closed)
 
 Contact us to add your project!
@@ -324,26 +325,84 @@ The `Embeddings` function can be used to obtain the emdeddings of a phrase:
 A <b>detailed documentation</b> on function level can be found here:
 <a href="https://undream.ai/LLMUnity"><img src="https://img.shields.io/badge/Documentation-white.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwEAYAAAAHkiXEAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAATqSURBVHic7ZtbiE1RGMc349K4M5EwklwjzUhJCMmTJPJAYjQXJJcH8+Blkry4lPJA8aAoJbekDLmUS6E8SHJL5AW5JPf77eHv93C22Wfttc/ee+0zc/4vv+bMXvusvfZa3/q+b33H80oqqaSSSmqrKnPdgXjUvbvYq5f4+7f486eb/rRajRsn7t4tPngg/vol/vkj/vghXr0q7tghzpyZ//79+on79omXLombNondukXrd9GoSxdx8mSxqUm8eVNkgAvl0aPioEFip07i6dP52z15Ig4fbvVY2VVFhbhokXjrlogJiWvAg/jwoXjqVO73+leUny9eiFVV5mfMlLDRBw+KX76ISQ+0LZ8/F00v4uJFsWPHFh83O+rdWzx3TnQ9wCZ+/Sqyl5iux1RmTu3aiYcPi64H1pasALypoOv4/8SJXraEbXc9kLbECxo2TKyuFj9/zt9u+XIvG8LWv3wpuh5QW86f3/JznT+fv93s2S23C1Z72wbhtH692LdvMvdPSgzkhAkiJhT16ZO/PRPOmcr+Rda4aa5nclTeuZP7PDgRpr1g40bPrQYOFF0PYKHEC+raVVy8OFy7R49EArvURU4mrUAqaTY0iB8/2rXD+XCm5mbR9QAWylevorV7/VpkL0ld06eLpkiyWPj9u93179+LpFZwZ1PXtGnitWui64GMStPmG7SH1NSIJBNHjvTSFZvRvHlise0N9JcBtW1/44Y4dqx45IjnU0JxAGLpklPx+9VZFwPp/9v/eZDGjxcZh7dv4+mXtch+up7Rca+MsJvxiRNi6nvBhg25HWprZMaPGeOlqxEjxGKz+XGRTAAmyJnq6sR370TXA2NLW+8HNjZ62dLOnaLrAQ1r2zmqPH482n0mTfJCKmEvCJHUooNZE/369Elct06kqiKsONRfulTEFDsX8QDlIa5nup9374pE8IiZHPY+ly+LZE/37/cM6mC6IB6Vl4urV6fzfUG6d0/csyf37wsXRFInaM4ckTjGdPg+apTYs6dI3RIWwH//1DV1qkiuxNY2FzrTd+2y6y8z2HQU6efZs+KBAyJZ4v+V0h6ArlwROaQP0uPH4ooV4sqV8Xz/4MF211M2wwoOq1mzRAq5Pnywa5+4KDHE9mI7ly0TO3fOvZ6/eZCoKwB32HS0SMFV1DNtImBKHYstBROoQ4fEQk2RaS+qrxejmj5M7NatIhWARS82xUJfAKahzFcdPnq0GLYgy7Rnbd8e6rGKRyzpuNzPBQty709RcNSZf/KkuHCh2GpMDyKbGNcLYE+YMkVks336NFx7XhTZ3szXiBaqtWvFuAOxM2dEZiyH8UErgc8JLNun7E0aFffSI7RP6owZmz9kSO73HjsmXr8ukppYsybSYyQvBp5QfOjQ3M9tRR496pGgLf1JtLlzRZJzlFzGp4SWDnUxFCrdvy+uWiWa3DJe3N69oj8uSEq8CER88uaNOGBAOv2ILGY69TBBJoM8O0t72zaRoztXBzlLlrT8XARW/IQq82JTMv3mKmv0/9CC4mJMYPwrMSETxAyurRUxQVmXP1fEid7mzeK3b+n2Jzb16CFu2SIWmtNJiriVxANsyq0uoCJfTk4G9y4t24/bSQ0rTkP6gVTG3mz//uKMGSK/ucId5Xe9lZUi5eMMLGUgz56J5Hxu3xZ50Xg3RMIltVn9BRja26PYsBHgAAAAAElFTkSuQmCC"/></a>
 
-## Examples
-The [Samples~](Samples~) folder contains several examples of interaction 🤖:
-- [SimpleInteraction](Samples~/SimpleInteraction): Demonstrates a simple interaction with an AI character
-- [MultipleCharacters](Samples~/MultipleCharacters): Demonstrates a simple interaction using multiple AI characters
-- [KnowledgeBaseGame](Samples~/KnowledgeBaseGame): Simple detective game using a knowledge base to provide information to the LLM based on [google/mysteryofthreebots](https://github.com/google/mysteryofthreebots)
-- [ChatBot](Samples~/ChatBot): Demonstrates interaction between a player and a AI with a UI similar to a messaging app (see image below)
-- [AndroidDemo](Samples~/AndroidDemo): Example Android app with an initial screen with model download progress
-  
-<img width="400" src=".github/demo.gif">
+## Semantic search with a Retrieval-Augmented Generation (RAG) system
+LLM for Unity implements a super-fast similarity search functionality with a Retrieval-Augmented Generation (RAG) system.<br>
+It is based on the LLM functionality, and the Approximate Nearest Neighbors (ANN) search from the [usearch](https://github.com/unum-cloud/usearch) library.<br>
+Semantic search works as follows.
 
-To install a sample:
-- Open the Package Manager: `Window > Package Manager`
-- Select the `LLM for Unity` Package. From the `Samples` Tab, click `Import` next to the sample you want to install.
+**Building the data** You provide text inputs (a phrase, paragraph, document) to add to the data.<br>
+Each input is split into chunks (optional) and encoded into embeddings with a LLM.
 
-The samples can be run with the `Scene.unity` scene they contain inside their folder.<br>
-In the scene, select the `LLM` GameObject and click the `Download Model` button to download a default model or `Load model` to load your own model (see [LLM model management](#llm-model-management)).<br>
-Save the scene, run and enjoy!
+**Searching** You can then search for a query text input. <br>
+The input is again encoded and the most similar text inputs or chunks in the data are retrieved.
+
+To use semantic serch:
+- create a GameObject for the LLM as described above. Download one of the provided RAG models or load your own (good options can be found at the [MTEB leaderboard](https://huggingface.co/spaces/mteb/leaderboard)).
+- create an empty GameObject. In the GameObject Inspector click `Add Component` and select the `RAG` script.
+- In the Search Type dropdown of the RAG select your preferred search method. `SimpleSearch` is a simple brute-force search, while`DBSearch` is a fast ANN method that should be preferred in most cases.
+- In the Chunking Type dropdown of the RAG you can select a method for splitting the inputs into chunks. This is useful to have a more consistent meaning within each data part. Chunking methods for splitting according to tokens, words and sentences are provided.
+
+Alternatively, you can create the RAG from code (where llm is your LLM):
+``` c#
+  RAG rag = gameObject.AddComponent<RAG>();
+  rag.Init(SearchMethods.DBSearch, ChunkingMethods.SentenceSplitter, llm);
+```
+
+In your script you can then use it as follows :unicorn::
+``` c#
+using LLMUnity;
+
+public class MyScript : MonoBehaviour
+{
+  RAG rag;
+
+  async void Game(){
+    ...
+    string[] inputs = new string[]{
+      "Hi! I'm a search system.",
+      "the weather is nice. I like it.",
+      "I'm a RAG system"
+    };
+    // add the inputs to the RAG
+    foreach (string input in inputs) await rag.Add(input);
+    // get the 2 most similar inputs and their distance (dissimilarity) to the search query
+    (string[] results, float[] distances) = await rag.Search("hello!", 2);
+    // to get the most similar text parts (chnuks) you can enable the returnChunks option
+    rag.ReturnChunks(true);
+    (results, distances) = await rag.Search("hello!", 2);
+    ...
+  }
+}
+```
+
+You can save the RAG state (stored in the `Assets/StreamingAssets` folder):
+``` c#
+rag.Save("rag.zip");
+```
+and load it from disk:
+``` c#
+await rag.Load("rag.zip");
+```
+
+You can use the RAG to feed relevant data to the LLM based on a user message:
+``` c#
+  string message = "How is the weather?";
+  (string[] similarPhrases, float[] distances) = await rag.Search(message, 3);
+
+  string prompt = "Answer the user query based on the provided data.\n\n";
+  prompt += $"User query: {message}\n\n";
+  prompt += $"Data:\n";
+  foreach (string similarPhrase in similarPhrases) prompt += $"\n- {similarPhrase}";
+
+  _ = llmCharacter.Chat(prompt, HandleReply, ReplyCompleted);
+```
+
+The `RAG` sample includes an example RAG implementation as well as an example RAG-LLM integration.
+
+That's all :sparkles:!
 
 ## LLM model management
-LLM for Unity implements a model manager that allows to load or download LLMs and ship them directly in your game.<br>
+LLM for Unity uses a model manager that allows to load or download LLMs and ship them directly in your game.<br>
 The model manager can be found as part of the LLM GameObject:<br>
 <img width="360" src=".github/LLM_manager.png">
 
@@ -368,6 +427,25 @@ If you have loaded a model locally you need to set its URL through the expanded
 
 ❕ Before using any model make sure you **check their license** ❕
 
+## Examples
+The [Samples~](Samples~) folder contains several examples of interaction 🤖:
+- [SimpleInteraction](Samples~/SimpleInteraction): Demonstrates a simple interaction with an AI character
+- [MultipleCharacters](Samples~/MultipleCharacters): Demonstrates a simple interaction using multiple AI characters
+- [RAG](Samples~/RAG): RAG sample. Includes an example using the RAG to feed information to a LLM
+- [ChatBot](Samples~/ChatBot): Demonstrates interaction between a player and a AI with a UI similar to a messaging app (see image below)
+- [KnowledgeBaseGame](Samples~/KnowledgeBaseGame): Simple detective game using a knowledge base to provide information to the LLM based on [google/mysteryofthreebots](https://github.com/google/mysteryofthreebots)
+- [AndroidDemo](Samples~/AndroidDemo): Example Android app with an initial screen with model download progress
+  
+<img width="400" src=".github/demo.gif">
+
+To install a sample:
+- Open the Package Manager: `Window > Package Manager`
+- Select the `LLM for Unity` Package. From the `Samples` Tab, click `Import` next to the sample you want to install.
+
+The samples can be run with the `Scene.unity` scene they contain inside their folder.<br>
+In the scene, select the `LLM` GameObject and click the `Download Model` button to download a default model or `Load model` to load your own model (see [LLM model management](#llm-model-management)).<br>
+Save the scene, run and enjoy!
+
 ## Options
 
 ### LLM Settings
@@ -465,6 +543,7 @@ If the user's GPU is not supported, the LLM will fall back to the CPU
 #### 🤗 Model Settings
 - `Stream` select to receive the reply from the model as it is produced (recommended!).<br>
 If it is not selected, the full reply from the model is received in one go
+- <details><summary><code>Num Predict</code> maximum number of tokens to predict (default: 256, -1 = infinity, -2 = until context filled)</summary>This is the maximum amount of tokens the model will maximum predict. When N tokens are reached the model will stop generating. This means words / sentences might not get finished if this is too low. </details>
 
 - <details><summary>Advanced options</summary>
 
@@ -473,7 +552,6 @@ If it is not selected, the full reply from the model is received in one go
   - <details><summary><code>Cache Prompt</code> save the ongoing prompt from the chat (default: true)</summary> Saves the prompt while it is being created by the chat to avoid reprocessing the entire prompt every time</details>
   - `Slot` slot of the server to use for computation. Value can be set from 0 to `Parallel Prompts`-1 (default: -1 = new slot for each character)
   - `Seed` seed for reproducibility. For random results every time use -1
-  - <details><summary><code>Num Predict</code> maximum number of tokens to predict (default: 256, -1 = infinity, -2 = until context filled)</summary>This is the maximum amount of tokens the model will maximum predict. When N tokens are reached the model will stop generating. This means words / sentences might not get finished if this is too low. </details>
   - <details><summary><code>Temperature</code> LLM temperature, lower values give more deterministic answers (default: 0.2)</summary>The temperature setting adjusts how random the generated responses are. Turning it up makes the generated choices more varied and unpredictable. Turning it down makes the generated responses more predictable and focused on the most likely options.</details>
   - <details><summary><code>Top K</code> top-k sampling (default: 40, 0 = disabled)</summary>The top k value controls the top k most probable tokens at each step of generation. This value can help fine tune the output and make this adhere to specific patterns or constraints.</details>
   - <details><summary><code>Top P</code> top-p sampling (default: 0.9, 1.0 = disabled)</summary>The top p value controls the cumulative probability of generated tokens. The model will generate tokens until this theshold (p) is reached. By lowering this value you can shorten output & encourage / discourage more diverse outputs.</details>
diff --git a/Resources/llmunity_trash_icon.png b/Resources/llmunity_trash_icon.png
index 7457cc94..6b6c79bb 100644
Binary files a/Resources/llmunity_trash_icon.png and b/Resources/llmunity_trash_icon.png differ
diff --git a/Resources/usearch.meta b/Resources/usearch.meta
new file mode 100644
index 00000000..43169347
--- /dev/null
+++ b/Resources/usearch.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 813e0c361e3df22d1bbed7d53f1b3405
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Resources/usearch/Android.meta b/Resources/usearch/Android.meta
new file mode 100644
index 00000000..81ceb1e3
--- /dev/null
+++ b/Resources/usearch/Android.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 70241b0f7760054458e1efc3bee9378e
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Resources/usearch/Android/libusearch_c.so b/Resources/usearch/Android/libusearch_c.so
new file mode 100755
index 00000000..34a66974
Binary files /dev/null and b/Resources/usearch/Android/libusearch_c.so differ
diff --git a/Resources/usearch/Android/libusearch_c.so.meta b/Resources/usearch/Android/libusearch_c.so.meta
new file mode 100644
index 00000000..06a03b6e
--- /dev/null
+++ b/Resources/usearch/Android/libusearch_c.so.meta
@@ -0,0 +1,81 @@
+fileFormatVersion: 2
+guid: 89858a294079f0656b5adca9284fd3ee
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  defineConstraints: []
+  isPreloaded: 0
+  isOverridable: 0
+  isExplicitlyReferenced: 0
+  validateReferences: 1
+  platformData:
+  - first:
+      : Any
+    second:
+      enabled: 0
+      settings:
+        Exclude Android: 0
+        Exclude Editor: 1
+        Exclude Linux64: 1
+        Exclude OSXUniversal: 1
+        Exclude Win: 1
+        Exclude Win64: 1
+        Exclude iOS: 1
+  - first:
+      Android: Android
+    second:
+      enabled: 1
+      settings:
+        AndroidSharedLibraryType: Executable
+        CPU: ARM64
+  - first:
+      Any: 
+    second:
+      enabled: 0
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+        DefaultValueInitialized: true
+        OS: AnyOS
+  - first:
+      Standalone: Linux64
+    second:
+      enabled: 0
+      settings:
+        CPU: None
+  - first:
+      Standalone: OSXUniversal
+    second:
+      enabled: 0
+      settings:
+        CPU: None
+  - first:
+      Standalone: Win
+    second:
+      enabled: 0
+      settings:
+        CPU: None
+  - first:
+      Standalone: Win64
+    second:
+      enabled: 0
+      settings:
+        CPU: None
+  - first:
+      iPhone: iOS
+    second:
+      enabled: 0
+      settings:
+        AddToEmbeddedBinaries: false
+        CPU: AnyCPU
+        CompileFlags: 
+        FrameworkDependencies: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Resources/usearch/arm64.meta b/Resources/usearch/arm64.meta
new file mode 100644
index 00000000..ebd946f8
--- /dev/null
+++ b/Resources/usearch/arm64.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0c04ff4356d23e89bad717a2f3d90f76
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Resources/usearch/arm64/libusearch_c.dylib b/Resources/usearch/arm64/libusearch_c.dylib
new file mode 100755
index 00000000..c2844232
Binary files /dev/null and b/Resources/usearch/arm64/libusearch_c.dylib differ
diff --git a/Resources/usearch/arm64/libusearch_c.dylib.meta b/Resources/usearch/arm64/libusearch_c.dylib.meta
new file mode 100644
index 00000000..cb9d789b
--- /dev/null
+++ b/Resources/usearch/arm64/libusearch_c.dylib.meta
@@ -0,0 +1,81 @@
+fileFormatVersion: 2
+guid: 14827c9a910bec82e8c03f98ae1690a6
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  defineConstraints: []
+  isPreloaded: 0
+  isOverridable: 0
+  isExplicitlyReferenced: 0
+  validateReferences: 1
+  platformData:
+  - first:
+      : Any
+    second:
+      enabled: 0
+      settings:
+        Exclude Android: 1
+        Exclude Editor: 0
+        Exclude Linux64: 1
+        Exclude OSXUniversal: 0
+        Exclude Win: 1
+        Exclude Win64: 1
+        Exclude iOS: 1
+  - first:
+      Android: Android
+    second:
+      enabled: 0
+      settings:
+        AndroidSharedLibraryType: Executable
+        CPU: ARMv7
+  - first:
+      Any: 
+    second:
+      enabled: 0
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 1
+      settings:
+        CPU: ARM64
+        DefaultValueInitialized: true
+        OS: OSX
+  - first:
+      Standalone: Linux64
+    second:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+  - first:
+      Standalone: OSXUniversal
+    second:
+      enabled: 1
+      settings:
+        CPU: AnyCPU
+  - first:
+      Standalone: Win
+    second:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+  - first:
+      Standalone: Win64
+    second:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+  - first:
+      iPhone: iOS
+    second:
+      enabled: 0
+      settings:
+        AddToEmbeddedBinaries: false
+        CPU: AnyCPU
+        CompileFlags: 
+        FrameworkDependencies: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Resources/usearch/x86_64.meta b/Resources/usearch/x86_64.meta
new file mode 100644
index 00000000..d4700003
--- /dev/null
+++ b/Resources/usearch/x86_64.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 757e0eb836e503359b5e8bda9cf170b4
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Resources/usearch/x86_64/libusearch_c.dll b/Resources/usearch/x86_64/libusearch_c.dll
new file mode 100644
index 00000000..c348c026
Binary files /dev/null and b/Resources/usearch/x86_64/libusearch_c.dll differ
diff --git a/Resources/usearch/x86_64/libusearch_c.dll.meta b/Resources/usearch/x86_64/libusearch_c.dll.meta
new file mode 100644
index 00000000..e4fd016f
--- /dev/null
+++ b/Resources/usearch/x86_64/libusearch_c.dll.meta
@@ -0,0 +1,81 @@
+fileFormatVersion: 2
+guid: 1a39157ce6e034612b0b8bc7bb1123f0
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  defineConstraints: []
+  isPreloaded: 0
+  isOverridable: 0
+  isExplicitlyReferenced: 0
+  validateReferences: 1
+  platformData:
+  - first:
+      : Any
+    second:
+      enabled: 0
+      settings:
+        Exclude Android: 1
+        Exclude Editor: 0
+        Exclude Linux64: 0
+        Exclude OSXUniversal: 0
+        Exclude Win: 0
+        Exclude Win64: 0
+        Exclude iOS: 1
+  - first:
+      Android: Android
+    second:
+      enabled: 0
+      settings:
+        AndroidSharedLibraryType: Executable
+        CPU: ARMv7
+  - first:
+      Any: 
+    second:
+      enabled: 0
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 1
+      settings:
+        CPU: AnyCPU
+        DefaultValueInitialized: true
+        OS: Windows
+  - first:
+      Standalone: Linux64
+    second:
+      enabled: 1
+      settings:
+        CPU: AnyCPU
+  - first:
+      Standalone: OSXUniversal
+    second:
+      enabled: 1
+      settings:
+        CPU: AnyCPU
+  - first:
+      Standalone: Win
+    second:
+      enabled: 1
+      settings:
+        CPU: AnyCPU
+  - first:
+      Standalone: Win64
+    second:
+      enabled: 1
+      settings:
+        CPU: AnyCPU
+  - first:
+      iPhone: iOS
+    second:
+      enabled: 0
+      settings:
+        AddToEmbeddedBinaries: false
+        CPU: AnyCPU
+        CompileFlags: 
+        FrameworkDependencies: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Resources/usearch/x86_64/libusearch_c.dylib b/Resources/usearch/x86_64/libusearch_c.dylib
new file mode 100755
index 00000000..87b3dad9
Binary files /dev/null and b/Resources/usearch/x86_64/libusearch_c.dylib differ
diff --git a/Resources/usearch/x86_64/libusearch_c.dylib.meta b/Resources/usearch/x86_64/libusearch_c.dylib.meta
new file mode 100644
index 00000000..9b54ff15
--- /dev/null
+++ b/Resources/usearch/x86_64/libusearch_c.dylib.meta
@@ -0,0 +1,81 @@
+fileFormatVersion: 2
+guid: 76745b441e10b8a42a51f03f13d7f2c6
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  defineConstraints: []
+  isPreloaded: 0
+  isOverridable: 0
+  isExplicitlyReferenced: 0
+  validateReferences: 1
+  platformData:
+  - first:
+      : Any
+    second:
+      enabled: 0
+      settings:
+        Exclude Android: 1
+        Exclude Editor: 0
+        Exclude Linux64: 1
+        Exclude OSXUniversal: 0
+        Exclude Win: 1
+        Exclude Win64: 1
+        Exclude iOS: 1
+  - first:
+      Android: Android
+    second:
+      enabled: 0
+      settings:
+        AndroidSharedLibraryType: Executable
+        CPU: ARMv7
+  - first:
+      Any: 
+    second:
+      enabled: 0
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 1
+      settings:
+        CPU: x86_64
+        DefaultValueInitialized: true
+        OS: OSX
+  - first:
+      Standalone: Linux64
+    second:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+  - first:
+      Standalone: OSXUniversal
+    second:
+      enabled: 1
+      settings:
+        CPU: AnyCPU
+  - first:
+      Standalone: Win
+    second:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+  - first:
+      Standalone: Win64
+    second:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+  - first:
+      iPhone: iOS
+    second:
+      enabled: 0
+      settings:
+        AddToEmbeddedBinaries: false
+        CPU: AnyCPU
+        CompileFlags: 
+        FrameworkDependencies: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Resources/usearch/x86_64/libusearch_c.so b/Resources/usearch/x86_64/libusearch_c.so
new file mode 100644
index 00000000..4e50d3c0
Binary files /dev/null and b/Resources/usearch/x86_64/libusearch_c.so differ
diff --git a/Resources/usearch/x86_64/libusearch_c.so.meta b/Resources/usearch/x86_64/libusearch_c.so.meta
new file mode 100644
index 00000000..fe9fbdc4
--- /dev/null
+++ b/Resources/usearch/x86_64/libusearch_c.so.meta
@@ -0,0 +1,81 @@
+fileFormatVersion: 2
+guid: ca18f428d0c19d091bda4fb1b8d952c0
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  defineConstraints: []
+  isPreloaded: 0
+  isOverridable: 0
+  isExplicitlyReferenced: 0
+  validateReferences: 1
+  platformData:
+  - first:
+      : Any
+    second:
+      enabled: 0
+      settings:
+        Exclude Android: 1
+        Exclude Editor: 0
+        Exclude Linux64: 0
+        Exclude OSXUniversal: 0
+        Exclude Win: 0
+        Exclude Win64: 0
+        Exclude iOS: 1
+  - first:
+      Android: Android
+    second:
+      enabled: 0
+      settings:
+        AndroidSharedLibraryType: Executable
+        CPU: ARMv7
+  - first:
+      Any: 
+    second:
+      enabled: 0
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 1
+      settings:
+        CPU: AnyCPU
+        DefaultValueInitialized: true
+        OS: Linux
+  - first:
+      Standalone: Linux64
+    second:
+      enabled: 1
+      settings:
+        CPU: AnyCPU
+  - first:
+      Standalone: OSXUniversal
+    second:
+      enabled: 1
+      settings:
+        CPU: AnyCPU
+  - first:
+      Standalone: Win
+    second:
+      enabled: 1
+      settings:
+        CPU: AnyCPU
+  - first:
+      Standalone: Win64
+    second:
+      enabled: 1
+      settings:
+        CPU: AnyCPU
+  - first:
+      iPhone: iOS
+    second:
+      enabled: 0
+      settings:
+        AddToEmbeddedBinaries: false
+        CPU: AnyCPU
+        CompileFlags: 
+        FrameworkDependencies: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/LLM.cs b/Runtime/LLM.cs
index 39121bb4..0bb7e9b4 100644
--- a/Runtime/LLM.cs
+++ b/Runtime/LLM.cs
@@ -31,7 +31,7 @@ public class LLM : MonoBehaviour
         [LLM] public int numGPULayers = 0;
         /// <summary> select to log the output of the LLM in the Unity Editor. </summary>
         [LLM] public bool debug = false;
-        /// <summary> number of prompts that can happen in parallel (-1 = number of LLMCharacter objects) </summary>
+        /// <summary> number of prompts that can happen in parallel (-1 = number of LLMCaller objects) </summary>
         [LLMAdvanced] public int parallelPrompts = -1;
         /// <summary> select to not destroy the LLM GameObject when loading a new Scene. </summary>
         [LLMAdvanced] public bool dontDestroyOnLoad = true;
@@ -40,7 +40,7 @@ public class LLM : MonoBehaviour
         [DynamicRange("minContextLength", "maxContextLength", false), Model] public int contextSize = 8192;
         /// <summary> Batch size for prompt processing. </summary>
         [ModelAdvanced] public int batchSize = 512;
-        /// <summary> a base prompt to use as a base for all LLMCharacter objects </summary>
+        /// <summary> a base prompt to use as a base for all LLMCaller objects </summary>
         [TextArea(5, 10), ChatAdvanced] public string basePrompt = "";
         /// <summary> Boolean set to true if the server has started and is ready to receive requests, false otherwise. </summary>
         public bool started { get; protected set; } = false;
@@ -80,7 +80,7 @@ public class LLM : MonoBehaviour
         public int maxContextLength = 0;
 
         IntPtr LLMObject = IntPtr.Zero;
-        List<LLMCharacter> clients = new List<LLMCharacter>();
+        List<LLMCaller> clients = new List<LLMCaller>();
         LLMLib llmlib;
         StreamWrapper logStreamWrapper = null;
         Thread llmThread = null;
@@ -91,6 +91,8 @@ public class LLM : MonoBehaviour
         public LoraManager loraManager = new LoraManager();
         string loraPre = "";
         string loraWeightsPre = "";
+        public bool embeddingsOnly = false;
+        public int embeddingLength = 0;
 
         /// \endcond
 
@@ -110,7 +112,6 @@ void OnValidate()
 
         /// <summary>
         /// The Unity Awake function that starts the LLM server.
-        /// The server can be started asynchronously if the asynchronousStartup option is set.
         /// </summary>
         public async void Awake()
         {
@@ -136,11 +137,18 @@ public async void Awake()
             if (basePrompt != "") await SetBasePrompt(basePrompt);
         }
 
+        /// <summary>
+        /// Allows to wait until the LLM is ready
+        /// </summary>
         public async Task WaitUntilReady()
         {
             while (!started) await Task.Yield();
         }
 
+        /// <summary>
+        /// Allows to wait until the LLM models are downloaded and ready
+        /// </summary>
+        /// <param name="downloadProgressCallback">function to call with the download progress (float)</param>
         public static async Task<bool> WaitUntilModelSetup(Callback<float> downloadProgressCallback = null)
         {
             if (downloadProgressCallback != null) LLMManager.downloadProgressCallbacks.Add(downloadProgressCallback);
@@ -148,6 +156,7 @@ public static async Task<bool> WaitUntilModelSetup(Callback<float> downloadProgr
             return !modelSetupFailed;
         }
 
+        /// \cond HIDE
         public static string GetLLMManagerAsset(string path)
         {
 #if UNITY_EDITOR
@@ -199,6 +208,8 @@ public static string GetLLMManagerAssetRuntime(string path)
             return path;
         }
 
+        /// \endcond
+
         /// <summary>
         /// Allows to set the model used by the LLM.
         /// The model provided is copied to the Assets/StreamingAssets folder that allows it to also work in the build.
@@ -216,6 +227,7 @@ public void SetModel(string path)
 
                 maxContextLength = modelEntry.contextLength;
                 if (contextSize > maxContextLength) contextSize = maxContextLength;
+                SetEmbeddings(modelEntry.embeddingLength, modelEntry.embeddingOnly);
                 if (contextSize == 0 && modelEntry.contextLength > 32768)
                 {
                     LLMUnitySetup.LogWarning($"The model {path} has very large context size ({modelEntry.contextLength}), consider setting it to a smaller value (<=32768) to avoid filling up the RAM");
@@ -319,6 +331,20 @@ public void SetTemplate(string templateName, bool setDirty = true)
 #endif
         }
 
+        /// <summary>
+        /// Set LLM Embedding parameters
+        /// </summary>
+        /// <param name="embeddingLength"> number of embedding dimensions </param>
+        /// <param name="embeddingsOnly"> if true, the LLM will be used only for embeddings </param>
+        public void SetEmbeddings(int embeddingLength, bool embeddingsOnly)
+        {
+            this.embeddingsOnly = embeddingsOnly;
+            this.embeddingLength = embeddingLength;
+#if UNITY_EDITOR
+            if (!EditorApplication.isPlaying) EditorUtility.SetDirty(this);
+#endif
+        }
+
         /// \cond HIDE
 
         string ReadFileContents(string path)
@@ -402,15 +428,16 @@ protected virtual string GetLlamaccpArguments()
 
             int slots = GetNumClients();
             string arguments = $"-m \"{modelPath}\" -c {contextSize} -b {batchSize} --log-disable -np {slots}";
+            if (embeddingsOnly) arguments += " --embedding";
+            if (numThreadsToUse > 0) arguments += $" -t {numThreadsToUse}";
+            arguments += loraArgument;
+            arguments += $" -ngl {numGPULayers}";
+            if (LLMUnitySetup.FullLlamaLib && flashAttention) arguments += $" --flash-attn";
             if (remote)
             {
                 arguments += $" --port {port} --host 0.0.0.0";
                 if (!String.IsNullOrEmpty(APIKey)) arguments += $" --api-key {APIKey}";
             }
-            if (numThreadsToUse > 0) arguments += $" -t {numThreadsToUse}";
-            arguments += loraArgument;
-            arguments += $" -ngl {numGPULayers}";
-            if (LLMUnitySetup.FullLlamaLib && flashAttention) arguments += $" --flash-attn";
 
             // the following is the equivalent for running from command line
             string serverCommand;
@@ -522,15 +549,15 @@ private void StartService()
         }
 
         /// <summary>
-        /// Registers a local LLMCharacter object.
-        /// This allows to bind the LLMCharacter "client" to a specific slot of the LLM.
+        /// Registers a local LLMCaller object.
+        /// This allows to bind the LLMCaller "client" to a specific slot of the LLM.
         /// </summary>
-        /// <param name="llmCharacter"></param>
+        /// <param name="llmCaller"></param>
         /// <returns></returns>
-        public int Register(LLMCharacter llmCharacter)
+        public int Register(LLMCaller llmCaller)
         {
-            clients.Add(llmCharacter);
-            int index = clients.IndexOf(llmCharacter);
+            clients.Add(llmCaller);
+            int index = clients.IndexOf(llmCaller);
             if (parallelPrompts != -1) return index % parallelPrompts;
             return index;
         }
diff --git a/Runtime/LLMBuilder.cs b/Runtime/LLMBuilder.cs
index 656a5443..7d9f58d2 100644
--- a/Runtime/LLMBuilder.cs
+++ b/Runtime/LLMBuilder.cs
@@ -1,3 +1,5 @@
+/// @file
+/// @brief File implementing the LLMUnity builder.
 using UnityEditor;
 using UnityEngine;
 using System.IO;
@@ -6,6 +8,10 @@
 #if UNITY_EDITOR
 namespace LLMUnity
 {
+    /// @ingroup utils
+    /// <summary>
+    /// Class implementing the LLMUnity builder.
+    /// </summary>
     public class LLMBuilder
     {
         static List<StringPair> movedPairs = new List<StringPair>();
@@ -18,6 +24,12 @@ private static void InitializeOnLoad()
             Reset();
         }
 
+        /// <summary>
+        /// Performs an action for a file or a directory recursively
+        /// </summary>
+        /// <param name="source">source file/directory</param>
+        /// <param name="target">targer file/directory</param>
+        /// <param name="actionCallback">action</param>
         public static void HandleActionFileRecursive(string source, string target, ActionCallback actionCallback)
         {
             if (File.Exists(source))
@@ -37,22 +49,41 @@ public static void HandleActionFileRecursive(string source, string target, Actio
             }
         }
 
+        /// <summary>
+        /// Overwrites a target file based on the source file
+        /// </summary>
+        /// <param name="source">source file</param>
+        /// <param name="target">target file</param>
         public static void CopyWithOverwrite(string source, string target)
         {
             File.Copy(source, target, true);
         }
 
+        /// <summary>
+        /// Copies a source file to a target file
+        /// </summary>
+        /// <param name="source">source file</param>
+        /// <param name="target">target file</param>
         public static void CopyPath(string source, string target)
         {
             HandleActionFileRecursive(source, target, CopyWithOverwrite);
         }
 
+        /// <summary>
+        /// Moves a source file to a target file
+        /// </summary>
+        /// <param name="source">source file</param>
+        /// <param name="target">target file</param>
         public static void MovePath(string source, string target)
         {
             HandleActionFileRecursive(source, target, File.Move);
             DeletePath(source);
         }
 
+        /// <summary>
+        /// Deletes a path after checking if we are allowed to
+        /// </summary>
+        /// <param name="path">path</param>
         public static bool DeletePath(string path)
         {
             if (!LLMUnitySetup.IsSubPath(path, LLMUnitySetup.GetAssetPath()) && !LLMUnitySetup.IsSubPath(path, BuildTempDir))
@@ -112,6 +143,10 @@ static void AddActionAddMeta(string target)
             AddTargetPair(target + ".meta");
         }
 
+        /// <summary>
+        /// Hides all the library platforms apart from the target platform by moving out their library folders outside of StreamingAssets
+        /// </summary>
+        /// <param name="platform">target platform</param>
         public static void HideLibraryPlatforms(string platform)
         {
             List<string> platforms = new List<string>(){ "windows", "macos", "linux", "android", "ios", "setup" };
@@ -134,12 +169,18 @@ public static void HideLibraryPlatforms(string platform)
             }
         }
 
+        /// <summary>
+        /// Bundles the model information
+        /// </summary>
         public static void BuildModels()
         {
             LLMManager.Build(CopyActionAddMeta);
             if (File.Exists(LLMUnitySetup.LLMManagerPath)) AddActionAddMeta(LLMUnitySetup.LLMManagerPath);
         }
 
+        /// <summary>
+        /// Bundles the models and libraries
+        /// </summary>
         public static void Build(string platform)
         {
             Directory.CreateDirectory(BuildTempDir);
@@ -147,6 +188,9 @@ public static void Build(string platform)
             BuildModels();
         }
 
+        /// <summary>
+        /// Resets the libraries back to their original state
+        /// </summary>
         public static void Reset()
         {
             if (!File.Exists(movedCache)) return;
diff --git a/Runtime/LLMCaller.cs b/Runtime/LLMCaller.cs
new file mode 100644
index 00000000..ac0949a3
--- /dev/null
+++ b/Runtime/LLMCaller.cs
@@ -0,0 +1,376 @@
+/// @file
+/// @brief File implementing the basic functionality for LLM callers.
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using UnityEngine;
+using UnityEngine.Networking;
+
+namespace LLMUnity
+{
+    [DefaultExecutionOrder(-2)]
+    /// @ingroup llm
+    /// <summary>
+    /// Class implementing calling of LLM functions (local and remote).
+    /// </summary>
+    public class LLMCaller : MonoBehaviour
+    {
+        /// <summary> toggle to show/hide advanced options in the GameObject </summary>
+        [HideInInspector] public bool advancedOptions = false;
+        /// <summary> toggle to use remote LLM server or local LLM </summary>
+        [LocalRemote] public bool remote = false;
+        /// <summary> the LLM object to use </summary>
+        [Local, SerializeField] protected LLM _llm;
+        public LLM llm
+        {
+            get => _llm;//whatever
+            set => SetLLM(value);
+        }
+
+        /// <summary> allows to use a server with API key </summary>
+        [Remote] public string APIKey;
+
+        /// <summary> host to use for the LLM server </summary>
+        [Remote] public string host = "localhost";
+        /// <summary> port to use for the LLM server </summary>
+        [Remote] public int port = 13333;
+        /// <summary> number of retries to use for the LLM server requests (-1 = infinite) </summary>
+        [Remote] public int numRetries = 10;
+
+        protected LLM _prellm;
+        protected List<(string, string)> requestHeaders;
+        protected List<UnityWebRequest> WIPRequests = new List<UnityWebRequest>();
+
+        /// <summary>
+        /// The Unity Awake function that initializes the state before the application starts.
+        /// The following actions are executed:
+        /// - the corresponding LLM server is defined (if ran locally)
+        /// - the grammar is set based on the grammar file
+        /// - the prompt and chat history are initialised
+        /// - the chat template is constructed
+        /// - the number of tokens to keep are based on the system prompt (if setNKeepToPrompt=true)
+        /// </summary>
+        public virtual void Awake()
+        {
+            // Start the LLM server in a cross-platform way
+            if (!enabled) return;
+
+            requestHeaders = new List<(string, string)> { ("Content-Type", "application/json") };
+            if (!remote)
+            {
+                AssignLLM();
+                if (llm == null)
+                {
+                    string error = $"No LLM assigned or detected for LLMCharacter {name}!";
+                    LLMUnitySetup.LogError(error);
+                    throw new Exception(error);
+                }
+            }
+            else
+            {
+                if (!String.IsNullOrEmpty(APIKey)) requestHeaders.Add(("Authorization", "Bearer " + APIKey));
+            }
+        }
+
+        /// <summary>
+        /// Sets the LLM object of the LLMCaller
+        /// </summary>
+        /// <param name="llmSet">LLM object</param>
+        protected virtual void SetLLM(LLM llmSet)
+        {
+            if (llmSet != null && !IsValidLLM(llmSet))
+            {
+                LLMUnitySetup.LogError(NotValidLLMError());
+                llmSet = null;
+            }
+            _llm = llmSet;
+            _prellm = _llm;
+        }
+
+        /// <summary>
+        /// Checks if a LLM is valid for the LLMCaller
+        /// </summary>
+        /// <param name="llmSet">LLM object</param>
+        /// <returns>bool specifying whether the LLM is valid</returns>
+        public virtual bool IsValidLLM(LLM llmSet)
+        {
+            return true;
+        }
+
+        /// <summary>
+        /// Checks if a LLM can be auto-assigned if the LLM of the LLMCaller is null
+        /// </summary>
+        /// <param name="llmSet"LLM object></param>
+        /// <returns>bool specifying whether the LLM can be auto-assigned</returns>
+        public virtual bool IsAutoAssignableLLM(LLM llmSet)
+        {
+            return true;
+        }
+
+        protected virtual string NotValidLLMError()
+        {
+            return $"Can't set LLM {llm.name} to {name}";
+        }
+
+        protected virtual void OnValidate()
+        {
+            if (_llm != _prellm) SetLLM(_llm);
+            AssignLLM();
+        }
+
+        protected virtual void Reset()
+        {
+            AssignLLM();
+        }
+
+        protected virtual void AssignLLM()
+        {
+            if (remote || llm != null) return;
+
+            List<LLM> validLLMs = new List<LLM>();
+            foreach (LLM foundllm in FindObjectsOfType<LLM>())
+            {
+                if (IsValidLLM(foundllm) && IsAutoAssignableLLM(foundllm)) validLLMs.Add(foundllm);
+            }
+            if (validLLMs.Count == 0) return;
+
+            llm = SortLLMsByBestMatching(validLLMs.ToArray())[0];
+            string msg = $"Assigning LLM {llm.name} to {GetType()} {name}";
+            if (llm.gameObject.scene != gameObject.scene) msg += $" from scene {llm.gameObject.scene}";
+            LLMUnitySetup.Log(msg);
+        }
+
+        protected virtual LLM[] SortLLMsByBestMatching(LLM[] arrayIn)
+        {
+            LLM[] array = (LLM[])arrayIn.Clone();
+            for (int i = 0; i < array.Length - 1; i++)
+            {
+                bool swapped = false;
+                for (int j = 0; j < array.Length - i - 1; j++)
+                {
+                    bool sameScene = array[j].gameObject.scene == array[j + 1].gameObject.scene;
+                    bool swap = (
+                        (!sameScene && array[j + 1].gameObject.scene == gameObject.scene) ||
+                        (sameScene && array[j].transform.GetSiblingIndex() > array[j + 1].transform.GetSiblingIndex())
+                    );
+                    if (swap)
+                    {
+                        LLM temp = array[j];
+                        array[j] = array[j + 1];
+                        array[j + 1] = temp;
+                        swapped = true;
+                    }
+                }
+                if (!swapped) break;
+            }
+            return array;
+        }
+
+        protected virtual List<int> TokenizeContent(TokenizeResult result)
+        {
+            // get the tokens from a tokenize result received from the endpoint
+            return result.tokens;
+        }
+
+        protected virtual string DetokenizeContent(TokenizeRequest result)
+        {
+            // get content from a chat result received from the endpoint
+            return result.content;
+        }
+
+        protected virtual List<float> EmbeddingsContent(EmbeddingsResult result)
+        {
+            // get content from a chat result received from the endpoint
+            return result.embedding;
+        }
+
+        protected virtual Ret ConvertContent<Res, Ret>(string response, ContentCallback<Res, Ret> getContent = null)
+        {
+            // template function to convert the json received and get the content
+            if (response == null) return default;
+            response = response.Trim();
+            if (response.StartsWith("data: "))
+            {
+                string responseArray = "";
+                foreach (string responsePart in response.Replace("\n\n", "").Split("data: "))
+                {
+                    if (responsePart == "") continue;
+                    if (responseArray != "") responseArray += ",\n";
+                    responseArray += responsePart;
+                }
+                response = $"{{\"data\": [{responseArray}]}}";
+            }
+            return getContent(JsonUtility.FromJson<Res>(response));
+        }
+
+        protected virtual void CancelRequestsLocal() {}
+
+        protected virtual void CancelRequestsRemote()
+        {
+            foreach (UnityWebRequest request in WIPRequests)
+            {
+                request.Abort();
+            }
+            WIPRequests.Clear();
+        }
+
+        /// <summary>
+        /// Cancel the ongoing requests e.g. Chat, Complete.
+        /// </summary>
+        // <summary>
+        public virtual void CancelRequests()
+        {
+            if (remote) CancelRequestsRemote();
+            else CancelRequestsLocal();
+        }
+
+        protected virtual async Task<Ret> PostRequestLocal<Res, Ret>(string json, string endpoint, ContentCallback<Res, Ret> getContent, Callback<Ret> callback = null)
+        {
+            // send a post request to the server and call the relevant callbacks to convert the received content and handle it
+            // this function has streaming functionality i.e. handles the answer while it is being received
+            while (!llm.failed && !llm.started) await Task.Yield();
+            string callResult = null;
+            switch (endpoint)
+            {
+                case "tokenize":
+                    callResult = await llm.Tokenize(json);
+                    break;
+                case "detokenize":
+                    callResult = await llm.Detokenize(json);
+                    break;
+                case "embeddings":
+                    callResult = await llm.Embeddings(json);
+                    break;
+                case "slots":
+                    callResult = await llm.Slot(json);
+                    break;
+                default:
+                    LLMUnitySetup.LogError($"Unknown endpoint {endpoint}");
+                    break;
+            }
+
+            Ret result = ConvertContent(callResult, getContent);
+            callback?.Invoke(result);
+            return result;
+        }
+
+        protected virtual async Task<Ret> PostRequestRemote<Res, Ret>(string json, string endpoint, ContentCallback<Res, Ret> getContent, Callback<Ret> callback = null)
+        {
+            // send a post request to the server and call the relevant callbacks to convert the received content and handle it
+            // this function has streaming functionality i.e. handles the answer while it is being received
+            if (endpoint == "slots")
+            {
+                LLMUnitySetup.LogError("Saving and loading is not currently supported in remote setting");
+                return default;
+            }
+
+            Ret result = default;
+            byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(json);
+            UnityWebRequest request = null;
+            string error = null;
+            int tryNr = numRetries;
+
+            while (tryNr != 0)
+            {
+                using (request = UnityWebRequest.Put($"{host}:{port}/{endpoint}", jsonToSend))
+                {
+                    WIPRequests.Add(request);
+
+                    request.method = "POST";
+                    if (requestHeaders != null)
+                    {
+                        for (int i = 0; i < requestHeaders.Count; i++)
+                            request.SetRequestHeader(requestHeaders[i].Item1, requestHeaders[i].Item2);
+                    }
+
+                    // Start the request asynchronously
+                    var asyncOperation = request.SendWebRequest();
+                    float lastProgress = 0f;
+                    // Continue updating progress until the request is completed
+                    while (!asyncOperation.isDone)
+                    {
+                        float currentProgress = request.downloadProgress;
+                        // Check if progress has changed
+                        if (currentProgress != lastProgress && callback != null)
+                        {
+                            callback?.Invoke(ConvertContent(request.downloadHandler.text, getContent));
+                            lastProgress = currentProgress;
+                        }
+                        // Wait for the next frame
+                        await Task.Yield();
+                    }
+                    WIPRequests.Remove(request);
+                    if (request.result == UnityWebRequest.Result.Success)
+                    {
+                        result = ConvertContent(request.downloadHandler.text, getContent);
+                        error = null;
+                        break;
+                    }
+                    else
+                    {
+                        result = default;
+                        error = request.error;
+                        if (request.responseCode == (int)System.Net.HttpStatusCode.Unauthorized) break;
+                    }
+                }
+                tryNr--;
+                if (tryNr > 0) await Task.Delay(200 * (numRetries - tryNr));
+            }
+
+            if (error != null) LLMUnitySetup.LogError(error);
+            callback?.Invoke(result);
+            return result;
+        }
+
+        protected virtual async Task<Ret> PostRequest<Res, Ret>(string json, string endpoint, ContentCallback<Res, Ret> getContent, Callback<Ret> callback = null)
+        {
+            if (remote) return await PostRequestRemote(json, endpoint, getContent, callback);
+            return await PostRequestLocal(json, endpoint, getContent, callback);
+        }
+
+        /// <summary>
+        /// Tokenises the provided query.
+        /// </summary>
+        /// <param name="query">query to tokenise</param>
+        /// <param name="callback">callback function called with the result tokens</param>
+        /// <returns>list of the tokens</returns>
+        public virtual async Task<List<int>> Tokenize(string query, Callback<List<int>> callback = null)
+        {
+            // handle the tokenization of a message by the user
+            TokenizeRequest tokenizeRequest = new TokenizeRequest();
+            tokenizeRequest.content = query;
+            string json = JsonUtility.ToJson(tokenizeRequest);
+            return await PostRequest<TokenizeResult, List<int>>(json, "tokenize", TokenizeContent, callback);
+        }
+
+        /// <summary>
+        /// Detokenises the provided tokens to a string.
+        /// </summary>
+        /// <param name="tokens">tokens to detokenise</param>
+        /// <param name="callback">callback function called with the result string</param>
+        /// <returns>the detokenised string</returns>
+        public virtual async Task<string> Detokenize(List<int> tokens, Callback<string> callback = null)
+        {
+            // handle the detokenization of a message by the user
+            TokenizeResult tokenizeRequest = new TokenizeResult();
+            tokenizeRequest.tokens = tokens;
+            string json = JsonUtility.ToJson(tokenizeRequest);
+            return await PostRequest<TokenizeRequest, string>(json, "detokenize", DetokenizeContent, callback);
+        }
+
+        /// <summary>
+        /// Computes the embeddings of the provided input.
+        /// </summary>
+        /// <param name="tokens">input to compute the embeddings for</param>
+        /// <param name="callback">callback function called with the result string</param>
+        /// <returns>the computed embeddings</returns>
+        public virtual async Task<List<float>> Embeddings(string query, Callback<List<float>> callback = null)
+        {
+            // handle the tokenization of a message by the user
+            TokenizeRequest tokenizeRequest = new TokenizeRequest();
+            tokenizeRequest.content = query;
+            string json = JsonUtility.ToJson(tokenizeRequest);
+            return await PostRequest<EmbeddingsResult, List<float>>(json, "embeddings", EmbeddingsContent, callback);
+        }
+    }
+}
diff --git a/Samples~/SimpleInteraction/TestDownload.cs.meta b/Runtime/LLMCaller.cs.meta
similarity index 83%
rename from Samples~/SimpleInteraction/TestDownload.cs.meta
rename to Runtime/LLMCaller.cs.meta
index 5c4986c8..03714d58 100644
--- a/Samples~/SimpleInteraction/TestDownload.cs.meta
+++ b/Runtime/LLMCaller.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: ca77155fbdc403fffad6c19155d4d894
+guid: 01594396c2699f0ecb48ead86a6b1bc5
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Runtime/LLMCharacter.cs b/Runtime/LLMCharacter.cs
index 9b1f5153..09967be1 100644
--- a/Runtime/LLMCharacter.cs
+++ b/Runtime/LLMCharacter.cs
@@ -1,5 +1,5 @@
 /// @file
-/// @brief File implementing the LLMCharacter.
+/// @brief File implementing the LLM characters.
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -7,7 +7,6 @@
 using System.Threading.Tasks;
 using UnityEditor;
 using UnityEngine;
-using UnityEngine.Networking;
 
 namespace LLMUnity
 {
@@ -16,22 +15,8 @@ namespace LLMUnity
     /// <summary>
     /// Class implementing the LLM characters.
     /// </summary>
-    public class LLMCharacter : MonoBehaviour
+    public class LLMCharacter : LLMCaller
     {
-        /// <summary> toggle to show/hide advanced options in the GameObject </summary>
-        [HideInInspector] public bool advancedOptions = false;
-        /// <summary> toggle to use remote LLM server or local LLM </summary>
-        [LocalRemote] public bool remote = false;
-        /// <summary> the LLM object to use </summary>
-        [Local] public LLM llm;
-        /// <summary> host to use for the LLM server </summary>
-        [Remote] public string host = "localhost";
-        /// <summary> port to use for the LLM server </summary>
-        [Remote] public int port = 13333;
-        /// <summary> number of retries to use for the LLM server requests (-1 = infinite) </summary>
-        [Remote] public int numRetries = 10;
-        /// <summary> allows to use a server with API key </summary>
-        [Remote] public string APIKey;
         /// <summary> file to save the chat history.
         /// The file is saved only for Chat calls with addToHistory set to true.
         /// The file will be saved within the persistentDataPath directory (see https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html). </summary>
@@ -40,22 +25,19 @@ public class LLMCharacter : MonoBehaviour
         [LLM] public bool saveCache = false;
         /// <summary> select to log the constructed prompt the Unity Editor. </summary>
         [LLM] public bool debugPrompt = false;
-        /// <summary> option to receive the reply from the model as it is produced (recommended!).
-        /// If it is not selected, the full reply from the model is received in one go </summary>
-        [Model] public bool stream = true;
+        /// <summary> number of tokens to predict (-1 = infinity, -2 = until context filled).
+        /// This is the amount of tokens the model will maximum predict.
+        /// When N predict is reached the model will stop generating.
+        /// This means words / sentences might not get finished if this is too low. </summary>
+        [Model] public int numPredict = 256;
+        /// <summary> specify which slot of the server to use for computation (affects caching) </summary>
+        [ModelAdvanced] public int slot = -1;
         /// <summary> grammar file used for the LLM in .cbnf format (relative to the Assets/StreamingAssets folder) </summary>
         [ModelAdvanced] public string grammar = null;
         /// <summary> option to cache the prompt as it is being created by the chat to avoid reprocessing the entire prompt every time (default: true) </summary>
         [ModelAdvanced] public bool cachePrompt = true;
-        /// <summary> specify which slot of the server to use for computation (affects caching) </summary>
-        [ModelAdvanced] public int slot = -1;
         /// <summary> seed for reproducibility. For random results every time set to -1. </summary>
         [ModelAdvanced] public int seed = 0;
-        /// <summary> number of tokens to predict (-1 = infinity, -2 = until context filled).
-        /// This is the amount of tokens the model will maximum predict.
-        /// When N predict is reached the model will stop generating.
-        /// This means words / sentences might not get finished if this is too low. </summary>
-        [ModelAdvanced] public int numPredict = 256;
         /// <summary> LLM temperature, lower values give more deterministic answers.
         /// The temperature setting adjusts how random the generated responses are.
         /// Turning it up makes the generated choices more varied and unpredictable.
@@ -112,6 +94,9 @@ public class LLMCharacter : MonoBehaviour
         /// By providing a token ID and a positive or negative bias value, you can increase or decrease the probability of that token being generated. </summary>
         public Dictionary<int, string> logitBias = null;
 
+        /// <summary> option to receive the reply from the model as it is produced (recommended!).
+        /// If it is not selected, the full reply from the model is received in one go </summary>
+        [Chat] public bool stream = true;
         /// <summary> the name of the player </summary>
         [Chat] public string playerName = "user";
         /// <summary> the name of the AI </summary>
@@ -120,15 +105,15 @@ public class LLMCharacter : MonoBehaviour
         [TextArea(5, 10), Chat] public string prompt = "A chat between a curious human and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the human's questions.";
         /// <summary> option to set the number of tokens to retain from the prompt (nKeep) based on the LLMCharacter system prompt </summary>
         public bool setNKeepToPrompt = true;
-
-        /// \cond HIDE
+        /// <summary> the chat history as list of chat messages </summary>
         public List<ChatMessage> chat;
-        private SemaphoreSlim chatLock = new SemaphoreSlim(1, 1);
-        private string chatTemplate;
-        private ChatTemplate template = null;
+        /// <summary> the grammar to use </summary>
         public string grammarString;
-        private List<(string, string)> requestHeaders;
-        private List<UnityWebRequest> WIPRequests = new List<UnityWebRequest>();
+
+        /// \cond HIDE
+        protected SemaphoreSlim chatLock = new SemaphoreSlim(1, 1);
+        protected string chatTemplate;
+        protected ChatTemplate template = null;
         /// \endcond
 
         /// <summary>
@@ -140,88 +125,47 @@ public class LLMCharacter : MonoBehaviour
         /// - the chat template is constructed
         /// - the number of tokens to keep are based on the system prompt (if setNKeepToPrompt=true)
         /// </summary>
-        public void Awake()
+        public override void Awake()
         {
-            // Start the LLM server in a cross-platform way
             if (!enabled) return;
-
-            requestHeaders = new List<(string, string)> { ("Content-Type", "application/json") };
+            base.Awake();
             if (!remote)
             {
-                AssignLLM();
-                if (llm == null)
-                {
-                    LLMUnitySetup.LogError($"No LLM assigned or detected for LLMCharacter {name}!");
-                    return;
-                }
                 int slotFromServer = llm.Register(this);
                 if (slot == -1) slot = slotFromServer;
             }
-            else
-            {
-                if (!String.IsNullOrEmpty(APIKey)) requestHeaders.Add(("Authorization", "Bearer " + APIKey));
-            }
-
             InitGrammar();
             InitHistory();
         }
 
-        void OnValidate()
+        protected override void OnValidate()
         {
-            AssignLLM();
+            base.OnValidate();
             if (llm != null && llm.parallelPrompts > -1 && (slot < -1 || slot >= llm.parallelPrompts)) LLMUnitySetup.LogError($"The slot needs to be between 0 and {llm.parallelPrompts-1}, or -1 to be automatically set");
         }
 
-        void Reset()
+        protected override string NotValidLLMError()
         {
-            AssignLLM();
+            return base.NotValidLLMError() + $", it is an embedding only model";
         }
 
-        void AssignLLM()
+        /// <summary>
+        /// Checks if a LLM is valid for the LLMCaller
+        /// </summary>
+        /// <param name="llmSet">LLM object</param>
+        /// <returns>bool specifying whether the LLM is valid</returns>
+        public override bool IsValidLLM(LLM llmSet)
         {
-            if (remote || llm != null) return;
-
-            LLM[] existingLLMs = FindObjectsOfType<LLM>();
-            if (existingLLMs.Length == 0) return;
-
-            SortBySceneAndHierarchy(existingLLMs);
-            llm = existingLLMs[0];
-            string msg = $"Assigning LLM {llm.name} to LLMCharacter {name}";
-            if (llm.gameObject.scene != gameObject.scene) msg += $" from scene {llm.gameObject.scene}";
-            LLMUnitySetup.Log(msg);
+            return !llmSet.embeddingsOnly;
         }
 
-        void SortBySceneAndHierarchy(LLM[] array)
-        {
-            for (int i = 0; i < array.Length - 1; i++)
-            {
-                bool swapped = false;
-                for (int j = 0; j < array.Length - i - 1; j++)
-                {
-                    bool sameScene = array[j].gameObject.scene == array[j + 1].gameObject.scene;
-                    bool swap = (
-                        (!sameScene && array[j + 1].gameObject.scene == gameObject.scene) ||
-                        (sameScene && array[j].transform.GetSiblingIndex() > array[j + 1].transform.GetSiblingIndex())
-                    );
-                    if (swap)
-                    {
-                        LLM temp = array[j];
-                        array[j] = array[j + 1];
-                        array[j + 1] = temp;
-                        swapped = true;
-                    }
-                }
-                if (!swapped) break;
-            }
-        }
-
-        protected void InitHistory()
+        protected virtual void InitHistory()
         {
             InitPrompt();
             _ = LoadHistory();
         }
 
-        protected async Task LoadHistory()
+        protected virtual async Task LoadHistory()
         {
             if (save == "" || !File.Exists(GetJsonSavePath(save))) return;
             await chatLock.WaitAsync(); // Acquire the lock
@@ -235,22 +179,32 @@ protected async Task LoadHistory()
             }
         }
 
-        public virtual string GetSavePath(string filename)
+        protected virtual string GetSavePath(string filename)
         {
             return Path.Combine(Application.persistentDataPath, filename).Replace('\\', '/');
         }
 
+        /// <summary>
+        /// Allows to get the save path of the chat history based on the provided filename or relative path.
+        /// </summary>
+        /// <param name="filename">filename or relative path used for the save</param>
+        /// <returns>save path</returns>
         public virtual string GetJsonSavePath(string filename)
         {
             return GetSavePath(filename + ".json");
         }
 
+        /// <summary>
+        /// Allows to get the save path of the LLM cache based on the provided filename or relative path.
+        /// </summary>
+        /// <param name="filename">filename or relative path used for the save</param>
+        /// <returns>save path</returns>
         public virtual string GetCacheSavePath(string filename)
         {
             return GetSavePath(filename + ".cache");
         }
 
-        private void InitPrompt(bool clearChat = true)
+        protected virtual void InitPrompt(bool clearChat = true)
         {
             if (chat != null)
             {
@@ -276,14 +230,14 @@ private void InitPrompt(bool clearChat = true)
         /// </summary>
         /// <param name="newPrompt"> the system prompt </param>
         /// <param name="clearChat"> whether to clear (true) or keep (false) the current chat history on top of the system prompt. </param>
-        public void SetPrompt(string newPrompt, bool clearChat = true)
+        public virtual void SetPrompt(string newPrompt, bool clearChat = true)
         {
             prompt = newPrompt;
             nKeep = -1;
             InitPrompt(clearChat);
         }
 
-        private bool CheckTemplate()
+        protected virtual bool CheckTemplate()
         {
             if (template == null)
             {
@@ -293,7 +247,7 @@ private bool CheckTemplate()
             return true;
         }
 
-        private async Task<bool> InitNKeep()
+        protected virtual async Task<bool> InitNKeep()
         {
             if (setNKeepToPrompt && nKeep == -1)
             {
@@ -306,7 +260,7 @@ private async Task<bool> InitNKeep()
             return true;
         }
 
-        private void InitGrammar()
+        protected virtual void InitGrammar()
         {
             if (grammar != null && grammar != "")
             {
@@ -314,17 +268,17 @@ private void InitGrammar()
             }
         }
 
-        private void SetNKeep(List<int> tokens)
+        protected virtual void SetNKeep(List<int> tokens)
         {
             // set the tokens to keep
             nKeep = tokens.Count;
         }
 
         /// <summary>
-        /// Load the chat template of the LLMCharacter.
+        /// Loads the chat template of the LLMCharacter.
         /// </summary>
         /// <returns></returns>
-        public async Task LoadTemplate()
+        public virtual async Task LoadTemplate()
         {
             string llmTemplate;
             if (remote)
@@ -344,10 +298,10 @@ public async Task LoadTemplate()
         }
 
         /// <summary>
-        /// Set the grammar file of the LLMCharacter
+        /// Sets the grammar file of the LLMCharacter
         /// </summary>
         /// <param name="path">path to the grammar file</param>
-        public async void SetGrammar(string path)
+        public virtual async void SetGrammar(string path)
         {
 #if UNITY_EDITOR
             if (!EditorApplication.isPlaying) path = LLMUnitySetup.AddAsset(path);
@@ -357,7 +311,7 @@ public async void SetGrammar(string path)
             InitGrammar();
         }
 
-        List<string> GetStopwords()
+        protected virtual List<string> GetStopwords()
         {
             if (!CheckTemplate()) return null;
             List<string> stopAll = new List<string>(template.GetStop(playerName, AIName));
@@ -365,7 +319,7 @@ List<string> GetStopwords()
             return stopAll;
         }
 
-        ChatRequest GenerateRequest(string prompt)
+        protected virtual ChatRequest GenerateRequest(string prompt)
         {
             // setup the request struct
             ChatRequest chatRequest = new ChatRequest();
@@ -400,29 +354,42 @@ ChatRequest GenerateRequest(string prompt)
             return chatRequest;
         }
 
-        public void AddMessage(string role, string content)
+        /// <summary>
+        /// Allows to add a message in the chat history.
+        /// </summary>
+        /// <param name="role">message role (e.g. playerName or AIName)</param>
+        /// <param name="content">message content</param>
+        public virtual void AddMessage(string role, string content)
         {
             // add the question / answer to the chat list, update prompt
             chat.Add(new ChatMessage { role = role, content = content });
         }
 
-        public void AddPlayerMessage(string content)
+        /// <summary>
+        /// Allows to add a player message in the chat history.
+        /// </summary>
+        /// <param name="content">message content</param>
+        public virtual void AddPlayerMessage(string content)
         {
             AddMessage(playerName, content);
         }
 
-        public void AddAIMessage(string content)
+        /// <summary>
+        /// Allows to add a AI message in the chat history.
+        /// </summary>
+        /// <param name="content">message content</param>
+        public virtual void AddAIMessage(string content)
         {
             AddMessage(AIName, content);
         }
 
-        protected string ChatContent(ChatResult result)
+        protected virtual string ChatContent(ChatResult result)
         {
             // get content from a chat result received from the endpoint
             return result.content.Trim();
         }
 
-        protected string MultiChatContent(MultiChatResult result)
+        protected virtual string MultiChatContent(MultiChatResult result)
         {
             // get content from a chat result received from the endpoint
             string response = "";
@@ -433,7 +400,19 @@ protected string MultiChatContent(MultiChatResult result)
             return response.Trim();
         }
 
-        async Task<string> CompletionRequest(string json, Callback<string> callback = null)
+        protected virtual string SlotContent(SlotResult result)
+        {
+            // get the tokens from a tokenize result received from the endpoint
+            return result.filename;
+        }
+
+        protected virtual string TemplateContent(TemplateResult result)
+        {
+            // get content from a char result received from the endpoint in open AI format
+            return result.template;
+        }
+
+        protected virtual async Task<string> CompletionRequest(string json, Callback<string> callback = null)
         {
             string result = "";
             if (stream)
@@ -447,36 +426,6 @@ async Task<string> CompletionRequest(string json, Callback<string> callback = nu
             return result;
         }
 
-        protected string TemplateContent(TemplateResult result)
-        {
-            // get content from a char result received from the endpoint in open AI format
-            return result.template;
-        }
-
-        protected List<int> TokenizeContent(TokenizeResult result)
-        {
-            // get the tokens from a tokenize result received from the endpoint
-            return result.tokens;
-        }
-
-        protected string DetokenizeContent(TokenizeRequest result)
-        {
-            // get content from a chat result received from the endpoint
-            return result.content;
-        }
-
-        protected List<float> EmbeddingsContent(EmbeddingsResult result)
-        {
-            // get content from a chat result received from the endpoint
-            return result.embedding;
-        }
-
-        protected string SlotContent(SlotResult result)
-        {
-            // get the tokens from a tokenize result received from the endpoint
-            return result.filename;
-        }
-
         /// <summary>
         /// Chat functionality of the LLM.
         /// It calls the LLM completion based on the provided query including the previous chat history.
@@ -488,7 +437,7 @@ protected string SlotContent(SlotResult result)
         /// <param name="completionCallback">callback function called when the full response has been received</param>
         /// <param name="addToHistory">whether to add the user query to the chat history</param>
         /// <returns>the LLM response</returns>
-        public async Task<string> Chat(string query, Callback<string> callback = null, EmptyCallback completionCallback = null, bool addToHistory = true)
+        public virtual async Task<string> Chat(string query, Callback<string> callback = null, EmptyCallback completionCallback = null, bool addToHistory = true)
         {
             // handle a chat message by the user
             // call the callback function while the answer is received
@@ -541,7 +490,7 @@ public async Task<string> Chat(string query, Callback<string> callback = null, E
         /// <param name="callback">callback function that receives the response as string</param>
         /// <param name="completionCallback">callback function called when the full response has been received</param>
         /// <returns>the LLM response</returns>
-        public async Task<string> Complete(string prompt, Callback<string> callback = null, EmptyCallback completionCallback = null)
+        public virtual async Task<string> Complete(string prompt, Callback<string> callback = null, EmptyCallback completionCallback = null)
         {
             // handle a completion request by the user
             // call the callback function while the answer is received
@@ -564,7 +513,7 @@ public async Task<string> Complete(string prompt, Callback<string> callback = nu
         /// <param name="completionCallback">callback function called when the full response has been received</param>
         /// <param name="query">user prompt used during the initialisation (not added to history)</param>
         /// <returns>the LLM response</returns>
-        public async Task Warmup(EmptyCallback completionCallback = null)
+        public virtual async Task Warmup(EmptyCallback completionCallback = null)
         {
             await LoadTemplate();
             if (!CheckTemplate()) return;
@@ -582,57 +531,17 @@ public async Task Warmup(EmptyCallback completionCallback = null)
         /// Asks the LLM for the chat template to use.
         /// </summary>
         /// <returns>the chat template of the LLM</returns>
-        public async Task<string> AskTemplate()
+        public virtual async Task<string> AskTemplate()
         {
             return await PostRequest<TemplateResult, string>("{}", "template", TemplateContent);
         }
 
-        /// <summary>
-        /// Tokenises the provided query.
-        /// </summary>
-        /// <param name="query">query to tokenise</param>
-        /// <param name="callback">callback function called with the result tokens</param>
-        /// <returns>list of the tokens</returns>
-        public async Task<List<int>> Tokenize(string query, Callback<List<int>> callback = null)
-        {
-            // handle the tokenization of a message by the user
-            TokenizeRequest tokenizeRequest = new TokenizeRequest();
-            tokenizeRequest.content = query;
-            string json = JsonUtility.ToJson(tokenizeRequest);
-            return await PostRequest<TokenizeResult, List<int>>(json, "tokenize", TokenizeContent, callback);
-        }
-
-        /// <summary>
-        /// Detokenises the provided tokens to a string.
-        /// </summary>
-        /// <param name="tokens">tokens to detokenise</param>
-        /// <param name="callback">callback function called with the result string</param>
-        /// <returns>the detokenised string</returns>
-        public async Task<string> Detokenize(List<int> tokens, Callback<string> callback = null)
-        {
-            // handle the detokenization of a message by the user
-            TokenizeResult tokenizeRequest = new TokenizeResult();
-            tokenizeRequest.tokens = tokens;
-            string json = JsonUtility.ToJson(tokenizeRequest);
-            return await PostRequest<TokenizeRequest, string>(json, "detokenize", DetokenizeContent, callback);
-        }
-
-        /// <summary>
-        /// Computes the embeddings of the provided input.
-        /// </summary>
-        /// <param name="tokens">input to compute the embeddings for</param>
-        /// <param name="callback">callback function called with the result string</param>
-        /// <returns>the computed embeddings</returns>
-        public async Task<List<float>> Embeddings(string query, Callback<List<float>> callback = null)
+        protected override void CancelRequestsLocal()
         {
-            // handle the tokenization of a message by the user
-            TokenizeRequest tokenizeRequest = new TokenizeRequest();
-            tokenizeRequest.content = query;
-            string json = JsonUtility.ToJson(tokenizeRequest);
-            return await PostRequest<EmbeddingsResult, List<float>>(json, "embeddings", EmbeddingsContent, callback);
+            if (slot >= 0) llm.CancelRequest(slot);
         }
 
-        protected async Task<string> Slot(string filepath, string action)
+        protected virtual async Task<string> Slot(string filepath, string action)
         {
             SlotRequest slotRequest = new SlotRequest();
             slotRequest.id_slot = slot;
@@ -686,176 +595,40 @@ public virtual async Task<string> Load(string filename)
             return result;
         }
 
-        protected Ret ConvertContent<Res, Ret>(string response, ContentCallback<Res, Ret> getContent = null)
-        {
-            // template function to convert the json received and get the content
-            if (response == null) return default;
-            response = response.Trim();
-            if (response.StartsWith("data: "))
-            {
-                string responseArray = "";
-                foreach (string responsePart in response.Replace("\n\n", "").Split("data: "))
-                {
-                    if (responsePart == "") continue;
-                    if (responseArray != "") responseArray += ",\n";
-                    responseArray += responsePart;
-                }
-                response = $"{{\"data\": [{responseArray}]}}";
-            }
-            return getContent(JsonUtility.FromJson<Res>(response));
-        }
-
-        protected void CancelRequestsLocal()
+        protected override async Task<Ret> PostRequestLocal<Res, Ret>(string json, string endpoint, ContentCallback<Res, Ret> getContent, Callback<Ret> callback = null)
         {
-            if (slot >= 0) llm.CancelRequest(slot);
-        }
-
-        protected void CancelRequestsRemote()
-        {
-            foreach (UnityWebRequest request in WIPRequests)
-            {
-                request.Abort();
-            }
-            WIPRequests.Clear();
-        }
+            if (endpoint != "completion") return await base.PostRequestLocal(json, endpoint, getContent, callback);
 
-        /// <summary>
-        /// Cancel the ongoing requests e.g. Chat, Complete.
-        /// </summary>
-        // <summary>
-        public void CancelRequests()
-        {
-            if (remote) CancelRequestsRemote();
-            else CancelRequestsLocal();
-        }
+            while (!llm.failed && !llm.started) await Task.Yield();
 
-        protected async Task<Ret> PostRequestLocal<Res, Ret>(string json, string endpoint, ContentCallback<Res, Ret> getContent, Callback<Ret> callback = null)
-        {
-            // send a post request to the server and call the relevant callbacks to convert the received content and handle it
-            // this function has streaming functionality i.e. handles the answer while it is being received
             string callResult = null;
             bool callbackCalled = false;
-            while (!llm.failed && !llm.started) await Task.Yield();
-            switch (endpoint)
-            {
-                case "tokenize":
-                    callResult = await llm.Tokenize(json);
-                    break;
-                case "detokenize":
-                    callResult = await llm.Detokenize(json);
-                    break;
-                case "embeddings":
-                    callResult = await llm.Embeddings(json);
-                    break;
-                case "slots":
-                    callResult = await llm.Slot(json);
-                    break;
-                case "completion":
-                    Callback<string> callbackString = null;
-                    if (stream && callback != null)
-                    {
-                        if (typeof(Ret) == typeof(string))
-                        {
-                            callbackString = (strArg) =>
-                            {
-                                callback(ConvertContent(strArg, getContent));
-                            };
-                        }
-                        else
-                        {
-                            LLMUnitySetup.LogError($"wrong callback type, should be string");
-                        }
-                        callbackCalled = true;
-                    }
-                    callResult = await llm.Completion(json, callbackString);
-                    break;
-                default:
-                    LLMUnitySetup.LogError($"Unknown endpoint {endpoint}");
-                    break;
-            }
-
-            Ret result = ConvertContent(callResult, getContent);
-            if (!callbackCalled) callback?.Invoke(result);
-            return result;
-        }
-
-        protected async Task<Ret> PostRequestRemote<Res, Ret>(string json, string endpoint, ContentCallback<Res, Ret> getContent, Callback<Ret> callback = null)
-        {
-            // send a post request to the server and call the relevant callbacks to convert the received content and handle it
-            // this function has streaming functionality i.e. handles the answer while it is being received
-            if (endpoint == "slots")
-            {
-                LLMUnitySetup.LogError("Saving and loading is not currently supported in remote setting");
-                return default;
-            }
-
-            Ret result = default;
-            byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(json);
-            UnityWebRequest request = null;
-            string error = null;
-            int tryNr = numRetries;
-
-            while (tryNr != 0)
+            if (llm.embeddingsOnly) LLMUnitySetup.LogError("The LLM can't be used for completion, only for embeddings");
+            else
             {
-                using (request = UnityWebRequest.Put($"{host}:{port}/{endpoint}", jsonToSend))
+                Callback<string> callbackString = null;
+                if (stream && callback != null)
                 {
-                    WIPRequests.Add(request);
-
-                    request.method = "POST";
-                    if (requestHeaders != null)
-                    {
-                        for (int i = 0; i < requestHeaders.Count; i++)
-                            request.SetRequestHeader(requestHeaders[i].Item1, requestHeaders[i].Item2);
-                    }
-
-                    // Start the request asynchronously
-                    var asyncOperation = request.SendWebRequest();
-                    float lastProgress = 0f;
-                    // Continue updating progress until the request is completed
-                    while (!asyncOperation.isDone)
+                    if (typeof(Ret) == typeof(string))
                     {
-                        float currentProgress = request.downloadProgress;
-                        // Check if progress has changed
-                        if (currentProgress != lastProgress && callback != null)
+                        callbackString = (strArg) =>
                         {
-                            try
-                            {
-                                callback?.Invoke(ConvertContent(request.downloadHandler.text, getContent));
-                            }
-                            catch (Exception) {}
-                            lastProgress = currentProgress;
-                        }
-                        // Wait for the next frame
-                        await Task.Yield();
-                    }
-                    WIPRequests.Remove(request);
-                    if (request.result == UnityWebRequest.Result.Success)
-                    {
-                        result = ConvertContent(request.downloadHandler.text, getContent);
-                        error = null;
-                        break;
+                            callback(ConvertContent(strArg, getContent));
+                        };
                     }
                     else
                     {
-                        result = default;
-                        error = request.error;
-                        if (request.responseCode == (int)System.Net.HttpStatusCode.Unauthorized) break;
+                        LLMUnitySetup.LogError($"wrong callback type, should be string");
                     }
+                    callbackCalled = true;
                 }
-                tryNr--;
-                if (tryNr > 0) await Task.Delay(200 * (numRetries - tryNr));
+                callResult = await llm.Completion(json, callbackString);
             }
 
-            if (error != null) LLMUnitySetup.LogError(error);
-            callback?.Invoke(result);
+            Ret result = ConvertContent(callResult, getContent);
+            if (!callbackCalled) callback?.Invoke(result);
             return result;
         }
-
-        protected async Task<Ret> PostRequest<Res, Ret>(string json, string endpoint, ContentCallback<Res, Ret> getContent, Callback<Ret> callback = null)
-        {
-            if (remote) return await PostRequestRemote(json, endpoint, getContent, callback);
-            return await PostRequestLocal(json, endpoint, getContent, callback);
-        }
     }
 
     /// \cond HIDE
diff --git a/Runtime/LLMChatTemplates.cs b/Runtime/LLMChatTemplates.cs
index e5e436b0..a4048e9e 100644
--- a/Runtime/LLMChatTemplates.cs
+++ b/Runtime/LLMChatTemplates.cs
@@ -1,9 +1,7 @@
 /// @file
 /// @brief File implementing the chat templates.
-using System;
 using System.Collections.Generic;
 using System.IO;
-using UnityEngine;
 
 namespace LLMUnity
 {
diff --git a/Runtime/LLMClient.cs b/Runtime/LLMClient.cs
deleted file mode 100644
index ced665d3..00000000
--- a/Runtime/LLMClient.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using UnityEngine;
-
-namespace LLMUnity
-{
-    public class LLMClient : LLMCharacter
-    {
-        public LLMClient()
-        {
-            Debug.LogWarning("LLMClient is deprecated and will be removed from future versions. Please Use LLMCharacter instead.");
-        }
-    }
-}
diff --git a/Runtime/LLMEmbedder.cs b/Runtime/LLMEmbedder.cs
new file mode 100644
index 00000000..1a7962b5
--- /dev/null
+++ b/Runtime/LLMEmbedder.cs
@@ -0,0 +1,28 @@
+/// @file
+/// @brief File implementing the LLM embedder.
+using UnityEngine;
+
+namespace LLMUnity
+{
+    [DefaultExecutionOrder(-2)]
+    /// @ingroup llm
+    /// <summary>
+    /// Class implementing the LLM embedder.
+    /// </summary>
+    public class LLMEmbedder : LLMCaller
+    {
+        protected override void SetLLM(LLM llmSet)
+        {
+            base.SetLLM(llmSet);
+            if (llmSet != null && !llmSet.embeddingsOnly)
+            {
+                LLMUnitySetup.LogWarning($"The LLM {llmSet.name} set for LLMEmbeddings {gameObject.name} is not an embeddings-only model, accuracy may be sub-optimal");
+            }
+        }
+
+        public override bool IsAutoAssignableLLM(LLM llmSet)
+        {
+            return llmSet.embeddingsOnly;
+        }
+    }
+}
diff --git a/Runtime/LLMClient.cs.meta b/Runtime/LLMEmbedder.cs.meta
similarity index 83%
rename from Runtime/LLMClient.cs.meta
rename to Runtime/LLMEmbedder.cs.meta
index 0712da54..387b9e15 100644
--- a/Runtime/LLMClient.cs.meta
+++ b/Runtime/LLMEmbedder.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: e95e88cdd1b0a159692667660a065473
+guid: c6856fbefac554a38a7b8a4b353fd43d
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Runtime/LLMGGUF.cs b/Runtime/LLMGGUF.cs
index 2ebeaf80..84246604 100644
--- a/Runtime/LLMGGUF.cs
+++ b/Runtime/LLMGGUF.cs
@@ -125,6 +125,11 @@ public ReaderField GetField(string key)
             return null;
         }
 
+        /// <summary>
+        /// Allows to retrieve a single-valued GGUF field.
+        /// </summary>
+        /// <param name="key"> GGUF field to retrieve </param>
+        /// <returns> Retrieved location info as ReaderField </returns>
         public byte[] GetGenericField(string key)
         {
             ReaderField field = GetField(key);
diff --git a/Runtime/LLMLib.cs b/Runtime/LLMLib.cs
index 0732846a..945b3a88 100644
--- a/Runtime/LLMLib.cs
+++ b/Runtime/LLMLib.cs
@@ -9,6 +9,10 @@
 
 namespace LLMUnity
 {
+    /// @ingroup utils
+    /// <summary>
+    /// Class implementing a wrapper for a communication stream between Unity and the llama.cpp library (mainly for completion calls and logging).
+    /// </summary>
     public class StreamWrapper
     {
         LLMLib llmlib;
@@ -27,6 +31,11 @@ public StreamWrapper(LLMLib llmlib, Callback<string> callback, bool clearOnUpdat
             stringWrapper = (llmlib?.StringWrapper_Construct()).GetValueOrDefault();
         }
 
+        /// <summary>
+        /// Retrieves the content of the stream
+        /// </summary>
+        /// <param name="clear">whether to clear the stream after retrieving the content</param>
+        /// <returns>stream content</returns>
         public string GetString(bool clear = false)
         {
             string result;
@@ -57,6 +66,9 @@ public string GetString(bool clear = false)
             return result;
         }
 
+        /// <summary>
+        /// Unity Update implementation that retrieves the content and calls the callback if it has changed.
+        /// </summary>
         public void Update()
         {
             if (stringWrapper == IntPtr.Zero) return;
@@ -68,21 +80,39 @@ public void Update()
             }
         }
 
+        /// <summary>
+        /// Gets the stringWrapper object to pass to the library.
+        /// </summary>
+        /// <returns>stringWrapper object</returns>
         public IntPtr GetStringWrapper()
         {
             return stringWrapper;
         }
 
+        /// <summary>
+        /// Deletes the stringWrapper object.
+        /// </summary>
         public void Destroy()
         {
             if (stringWrapper != IntPtr.Zero) llmlib?.StringWrapper_Delete(stringWrapper);
         }
     }
 
+    /// @ingroup utils
+    /// <summary>
+    /// Class implementing a library loader for Unity.
+    /// Adapted from SkiaForUnity:
+    /// https://github.com/ammariqais/SkiaForUnity/blob/f43322218c736d1c41f3a3df9355b90db4259a07/SkiaUnity/Assets/SkiaSharp/SkiaSharp-Bindings/SkiaSharp.HarfBuzz.Shared/HarfBuzzSharp.Shared/LibraryLoader.cs
+    /// </summary>
     static class LibraryLoader
     {
-        // LibraryLoader is adapted from SkiaForUnity:
-        // https://github.com/ammariqais/SkiaForUnity/blob/f43322218c736d1c41f3a3df9355b90db4259a07/SkiaUnity/Assets/SkiaSharp/SkiaSharp-Bindings/SkiaSharp.HarfBuzz.Shared/HarfBuzzSharp.Shared/LibraryLoader.cs
+        /// <summary>
+        /// Allows to retrieve a function delegate for the library
+        /// </summary>
+        /// <typeparam name="T">type to cast the function</typeparam>
+        /// <param name="library">library handle</param>
+        /// <param name="name">function name</param>
+        /// <returns>function delegate</returns>
         public static T GetSymbolDelegate<T>(IntPtr library, string name) where T : Delegate
         {
             var symbol = GetSymbol(library, name);
@@ -92,6 +122,11 @@ public static T GetSymbolDelegate<T>(IntPtr library, string name) where T : Dele
             return Marshal.GetDelegateForFunctionPointer<T>(symbol);
         }
 
+        /// <summary>
+        /// Loads the provided library in a cross-platform manner
+        /// </summary>
+        /// <param name="libraryName">library path</param>
+        /// <returns>library handle</returns>
         public static IntPtr LoadLibrary(string libraryName)
         {
             if (string.IsNullOrEmpty(libraryName))
@@ -112,6 +147,12 @@ public static IntPtr LoadLibrary(string libraryName)
             return handle;
         }
 
+        /// <summary>
+        /// Retrieve a function delegate for the library in a cross-platform manner
+        /// </summary>
+        /// <param name="library">library handle</param>
+        /// <param name="symbolName">function name</param>
+        /// <returns>function handle</returns>
         public static IntPtr GetSymbol(IntPtr library, string symbolName)
         {
             if (string.IsNullOrEmpty(symbolName))
@@ -132,6 +173,10 @@ public static IntPtr GetSymbol(IntPtr library, string symbolName)
             return handle;
         }
 
+        /// <summary>
+        /// Frees up the library
+        /// </summary>
+        /// <param name="library">library handle</param>
         public static void FreeLibrary(IntPtr library)
         {
             if (library == IntPtr.Zero)
@@ -243,15 +288,12 @@ private static class Android
             public static IntPtr dlopen(string path) => dlopen(path, 1);
 
 #if UNITY_ANDROID
-            // LoadLibrary for Android
             [DllImport("__Internal")]
             public static extern IntPtr dlopen(string filename, int flags);
 
-            // GetSymbol for Android
             [DllImport("__Internal")]
             public static extern IntPtr dlsym(IntPtr handle, string symbol);
 
-            // FreeLibrary for Android
             [DllImport("__Internal")]
             public static extern int dlclose(IntPtr handle);
 #else
@@ -274,6 +316,10 @@ public static int dlclose(IntPtr handle)
         }
     }
 
+    /// @ingroup utils
+    /// <summary>
+    /// Class implementing the LLM library handling
+    /// </summary>
     public class LLMLib
     {
         IntPtr libraryHandle = IntPtr.Zero;
@@ -315,6 +361,11 @@ static LLMLib()
             }
         }
 
+        /// <summary>
+        /// Loads the library and function handles for the defined architecture
+        /// </summary>
+        /// <param name="arch">archtecture</param>
+        /// <exception cref="Exception"></exception>
         public LLMLib(string arch)
         {
             libraryHandle = LibraryLoader.LoadLibrary(GetArchitecturePath(arch));
@@ -349,11 +400,19 @@ public LLMLib(string arch)
             StopLogging = LibraryLoader.GetSymbolDelegate<StopLoggingDelegate>(libraryHandle, "StopLogging");
         }
 
+        /// <summary>
+        /// Destroys the LLM library
+        /// </summary>
         public void Destroy()
         {
             if (libraryHandle != IntPtr.Zero) LibraryLoader.FreeLibrary(libraryHandle);
         }
 
+        /// <summary>
+        /// Identifies the possible architectures that we can use based on the OS and GPU usage
+        /// </summary>
+        /// <param name="gpu">whether to allow GPU architectures</param>
+        /// <returns>possible architectures</returns>
         public static List<string> PossibleArchitectures(bool gpu = false)
         {
             List<string> architectures = new List<string>();
@@ -409,6 +468,10 @@ public static List<string> PossibleArchitectures(bool gpu = false)
             return architectures;
         }
 
+        /// <summary>
+        /// Gets the path of a library that allows to detect the underlying CPU (Windows / Linux).
+        /// </summary>
+        /// <returns>architecture checker library path</returns>
         public static string GetArchitectureCheckerPath()
         {
             string filename;
@@ -427,6 +490,11 @@ public static string GetArchitectureCheckerPath()
             return Path.Combine(LLMUnitySetup.libraryPath, filename);
         }
 
+        /// <summary>
+        /// Gets the path of the llama.cpp library for the specified architecture.
+        /// </summary>
+        /// <param name="arch">architecture</param>
+        /// <returns>llama.cpp library path</returns>
         public static string GetArchitecturePath(string arch)
         {
             string filename;
@@ -455,6 +523,11 @@ public static string GetArchitecturePath(string arch)
             return Path.Combine(LLMUnitySetup.libraryPath, filename);
         }
 
+        /// <summary>
+        /// Allows to retrieve a string from the library (Unity only allows marshalling of chars)
+        /// </summary>
+        /// <param name="stringWrapper">string wrapper pointer</param>
+        /// <returns>retrieved string</returns>
         public string GetStringWrapperResult(IntPtr stringWrapper)
         {
             string result = "";
diff --git a/Runtime/LLMManager.cs b/Runtime/LLMManager.cs
index ba97ca3b..412236bd 100644
--- a/Runtime/LLMManager.cs
+++ b/Runtime/LLMManager.cs
@@ -1,3 +1,5 @@
+/// @file
+/// @brief File implementing the LLM model manager
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -8,6 +10,10 @@
 namespace LLMUnity
 {
     [Serializable]
+    /// @ingroup utils
+    /// <summary>
+    /// Class implementing a LLM model entry
+    /// </summary>
     public class ModelEntry
     {
         public string label;
@@ -16,9 +22,18 @@ public class ModelEntry
         public bool lora;
         public string chatTemplate;
         public string url;
+        public bool embeddingOnly;
+        public int embeddingLength;
         public bool includeInBuild;
         public int contextLength;
 
+        static List<string> embeddingOnlyArchs = new List<string> {"bert", "nomic-bert", "jina-bert-v2", "t5", "t5encoder"};
+
+        /// <summary>
+        /// Returns the relative asset path if it is in the AssetPath folder (StreamingAssets or persistentPath), otherwise the filename.
+        /// </summary>
+        /// <param name="path">asset path</param>
+        /// <returns>relative asset path or filename</returns>
         public static string GetFilenameOrRelativeAssetPath(string path)
         {
             string assetPath = LLMUnitySetup.GetAssetPath(path); // Note: this will return the full path if a full path is passed
@@ -30,6 +45,13 @@ public static string GetFilenameOrRelativeAssetPath(string path)
             return Path.GetFileName(path);
         }
 
+        /// <summary>
+        /// Constructs a LLM model entry
+        /// </summary>
+        /// <param name="path">model path</param>
+        /// <param name="lora">if it is a LORA or LLM</param>
+        /// <param name="label">label to show in the model manager in the Editor</param>
+        /// <param name="url">model url</param>
         public ModelEntry(string path, bool lora = false, string label = null, string url = null)
         {
             filename = GetFilenameOrRelativeAssetPath(path);
@@ -40,15 +62,26 @@ public ModelEntry(string path, bool lora = false, string label = null, string ur
             includeInBuild = true;
             chatTemplate = null;
             contextLength = -1;
+            embeddingOnly = false;
+            embeddingLength = 0;
             if (!lora)
             {
                 GGUFReader reader = new GGUFReader(this.path);
-                chatTemplate = ChatTemplate.FromGGUF(reader, this.path);
                 string arch = reader.GetStringField("general.architecture");
-                if (arch != null) contextLength = reader.GetIntField($"{arch}.context_length");
+                if (arch != null)
+                {
+                    contextLength = reader.GetIntField($"{arch}.context_length");
+                    embeddingLength = reader.GetIntField($"{arch}.embedding_length");
+                }
+                embeddingOnly = embeddingOnlyArchs.Contains(arch);
+                chatTemplate = embeddingOnly ? default : ChatTemplate.FromGGUF(reader, this.path);
             }
         }
 
+        /// <summary>
+        /// Returns only the required fields for bundling the model in the build
+        /// </summary>
+        /// <returns>Adapted model entry</returns>
         public ModelEntry OnlyRequiredFields()
         {
             ModelEntry entry = (ModelEntry)MemberwiseClone();
@@ -58,14 +91,20 @@ public ModelEntry OnlyRequiredFields()
         }
     }
 
+    /// \cond HIDE
     [Serializable]
     public class LLMManagerStore
     {
         public bool downloadOnStart;
         public List<ModelEntry> modelEntries;
     }
+    /// \endcond
 
     [DefaultExecutionOrder(-2)]
+    /// @ingroup utils
+    /// <summary>
+    /// Class implementing the LLM model manager
+    /// </summary>
     public class LLMManager
     {
         public static bool downloadOnStart = false;
@@ -80,12 +119,20 @@ public class LLMManager
         static long currFileSize;
         static long completedSize;
 
+        /// <summary>
+        /// Sets the model download progress in all registered callbacks
+        /// </summary>
+        /// <param name="progress">model download progress</param>
         public static void SetDownloadProgress(float progress)
         {
             downloadProgress = (completedSize + progress * currFileSize) / totalSize;
             foreach (Callback<float> downloadProgressCallback in downloadProgressCallbacks) downloadProgressCallback?.Invoke(downloadProgress);
         }
 
+        /// <summary>
+        /// Setup of the models
+        /// </summary>
+        /// <returns>bool specifying if the setup was successful</returns>
         public static Task<bool> Setup()
         {
             lock (lockObject)
@@ -95,6 +142,10 @@ public static Task<bool> Setup()
             return SetupTask;
         }
 
+        /// <summary>
+        /// Task performing the setup of the models
+        /// </summary>
+        /// <returns>bool specifying if the setup was successful</returns>
         public static async Task<bool> SetupOnce()
         {
             await LLMUnitySetup.AndroidExtractAsset(LLMUnitySetup.LLMManagerPath, true);
@@ -152,11 +203,21 @@ public static async Task<bool> SetupOnce()
             return true;
         }
 
+        /// <summary>
+        /// Sets the chat template for a model and distributes it to all LLMs using it
+        /// </summary>
+        /// <param name="filename">model path</param>
+        /// <param name="chatTemplate">chat template</param>
         public static void SetTemplate(string filename, string chatTemplate)
         {
             SetTemplate(Get(filename), chatTemplate);
         }
 
+        /// <summary>
+        /// Sets the chat template for a model and distributes it to all LLMs using it
+        /// </summary>
+        /// <param name="entry">model entry</param>
+        /// <param name="chatTemplate">chat template</param>
         public static void SetTemplate(ModelEntry entry, string chatTemplate)
         {
             if (entry == null) return;
@@ -170,6 +231,11 @@ public static void SetTemplate(ModelEntry entry, string chatTemplate)
 #endif
         }
 
+        /// <summary>
+        /// Gets the model entry for a model path
+        /// </summary>
+        /// <param name="path">model path</param>
+        /// <returns>model entry</returns>
         public static ModelEntry Get(string path)
         {
             string filename = Path.GetFileName(path);
@@ -181,6 +247,11 @@ public static ModelEntry Get(string path)
             return null;
         }
 
+        /// <summary>
+        /// Gets the asset path based on whether the application runs locally in the editor or in a build
+        /// </summary>
+        /// <param name="filename">model filename or relative path</param>
+        /// <returns>asset path</returns>
         public static string GetAssetPath(string filename)
         {
             ModelEntry entry = Get(filename);
@@ -192,6 +263,11 @@ public static string GetAssetPath(string filename)
 #endif
         }
 
+        /// <summary>
+        /// Returns the number of LLM/LORA models
+        /// </summary>
+        /// <param name="lora">whether to return number of LORA or LLM models</param>
+        /// <returns>number of LLM/LORA models</returns>
         public static int Num(bool lora)
         {
             int num = 0;
@@ -202,26 +278,45 @@ public static int Num(bool lora)
             return num;
         }
 
+        /// <summary>
+        /// Returns the number of LLM models
+        /// </summary>
+        /// <returns>number of LLM models</returns>
         public static int NumModels()
         {
             return Num(false);
         }
 
+        /// <summary>
+        /// Returns the number of LORA models
+        /// </summary>
+        /// <returns>number of LORA models</returns>
         public static int NumLoras()
         {
             return Num(true);
         }
 
+        /// <summary>
+        /// Registers a LLM to the model manager
+        /// </summary>
+        /// <param name="llm">LLM</param>
         public static void Register(LLM llm)
         {
             llms.Add(llm);
         }
 
+        /// <summary>
+        /// Removes a LLM from the model manager
+        /// </summary>
+        /// <param name="llm">LLM</param>
         public static void Unregister(LLM llm)
         {
             llms.Remove(llm);
         }
 
+        /// <summary>
+        /// Loads the model manager from a file
+        /// </summary>
         public static void LoadFromDisk()
         {
             if (!File.Exists(LLMUnitySetup.LLMManagerPath)) return;
@@ -242,6 +337,11 @@ static void InitializeOnLoad()
             Load();
         }
 
+        /// <summary>
+        /// Adds a model entry to the model manager
+        /// </summary>
+        /// <param name="entry">model entry</param>
+        /// <returns>model filename</returns>
         public static string AddEntry(ModelEntry entry)
         {
             int indexToInsert = modelEntries.Count;
@@ -265,11 +365,27 @@ public static string AddEntry(ModelEntry entry)
             return entry.filename;
         }
 
+        /// <summary>
+        /// Creates and adds a model entry to the model manager
+        /// </summary>
+        /// <param name="path">model path</param>
+        /// <param name="lora">if it is a LORA or LLM</param>
+        /// <param name="label">label to show in the model manager in the Editor</param>
+        /// <param name="url">model url</param>
+        /// <returns>model filename</returns>
         public static string AddEntry(string path, bool lora = false, string label = null, string url = null)
         {
             return AddEntry(new ModelEntry(path, lora, label, url));
         }
 
+        /// <summary>
+        /// Downloads a model and adds a model entry to the model manager
+        /// </summary>
+        /// <param name="url">model url</param>
+        /// <param name="lora">if it is a LORA or LLM</param>
+        /// <param name="log">whether to log</param>
+        /// <param name="label">model label</param>
+        /// <returns>model filename</returns>
         public static async Task<string> Download(string url, bool lora = false, bool log = false, string label = null)
         {
             foreach (ModelEntry entry in modelEntries)
@@ -315,6 +431,14 @@ public static async Task<string> Download(string url, bool lora = false, bool lo
             return AddEntry(modelPath, lora, label, url);
         }
 
+        /// <summary>
+        /// Loads a model from disk and adds a model entry to the model manager
+        /// </summary>
+        /// <param name="path">model path</param>
+        /// <param name="lora">if it is a LORA or LLM</param>
+        /// <param name="log">whether to log</param>
+        /// <param name="label">model label</param>
+        /// <returns>model filename</returns>
         public static string Load(string path, bool lora = false, bool log = false, string label = null)
         {
             ModelEntry entry = Get(path);
@@ -326,31 +450,69 @@ public static string Load(string path, bool lora = false, bool log = false, stri
             return AddEntry(path, lora, label);
         }
 
+        /// <summary>
+        /// Downloads a LLM model from disk and adds a model entry to the model manager
+        /// </summary>
+        /// <param name="url">model url</param>
+        /// <param name="log">whether to log</param>
+        /// <param name="label">model label</param>
+        /// <returns>model filename</returns>
         public static async Task<string> DownloadModel(string url, bool log = false, string label = null)
         {
             return await Download(url, false, log, label);
         }
 
+        /// <summary>
+        /// Downloads a Lora model from disk and adds a model entry to the model manager
+        /// </summary>
+        /// <param name="url">model url</param>
+        /// <param name="log">whether to log</param>
+        /// <param name="label">model label</param>
+        /// <returns>model filename</returns>
         public static async Task<string> DownloadLora(string url, bool log = false, string label = null)
         {
             return await Download(url, true, log, label);
         }
 
+        /// <summary>
+        /// Loads a LLM model from disk and adds a model entry to the model manager
+        /// </summary>
+        /// <param name="path">model path</param>
+        /// <param name="log">whether to log</param>
+        /// <param name="label">model label</param>
+        /// <returns>model filename</returns>
         public static string LoadModel(string path, bool log = false, string label = null)
         {
             return Load(path, false, log, label);
         }
 
+        /// <summary>
+        /// Loads a LORA model from disk and adds a model entry to the model manager
+        /// </summary>
+        /// <param name="path">model path</param>
+        /// <param name="log">whether to log</param>
+        /// <param name="label">model label</param>
+        /// <returns>model filename</returns>
         public static string LoadLora(string path, bool log = false, string label = null)
         {
             return Load(path, true, log, label);
         }
 
+        /// <summary>
+        /// Sets the URL for a model
+        /// </summary>
+        /// <param name="filename">model filename</param>
+        /// <param name="url">model URL</param>
         public static void SetURL(string filename, string url)
         {
             SetURL(Get(filename), url);
         }
 
+        /// <summary>
+        /// Sets the URL for a model
+        /// </summary>
+        /// <param name="entry">model entry</param>
+        /// <param name="url">model URL</param>
         public static void SetURL(ModelEntry entry, string url)
         {
             if (entry == null) return;
@@ -358,11 +520,21 @@ public static void SetURL(ModelEntry entry, string url)
             Save();
         }
 
+        /// <summary>
+        /// Sets whether to include a model to the build
+        /// </summary>
+        /// <param name="filename">model filename</param>
+        /// <param name="includeInBuild">whether to include it</param>
         public static void SetIncludeInBuild(string filename, bool includeInBuild)
         {
             SetIncludeInBuild(Get(filename), includeInBuild);
         }
 
+        /// <summary>
+        /// Sets whether to include a model to the build
+        /// </summary>
+        /// <param name="entry">model entry</param>
+        /// <param name="includeInBuild">whether to include it</param>
         public static void SetIncludeInBuild(ModelEntry entry, bool includeInBuild)
         {
             if (entry == null) return;
@@ -370,6 +542,10 @@ public static void SetIncludeInBuild(ModelEntry entry, bool includeInBuild)
             Save();
         }
 
+        /// <summary>
+        /// Sets whether to download files on start
+        /// </summary>
+        /// <param name="value">whether to download files</param>
         public static void SetDownloadOnStart(bool value)
         {
             downloadOnStart = value;
@@ -385,11 +561,19 @@ public static void SetDownloadOnStart(bool value)
             Save();
         }
 
+        /// <summary>
+        /// Removes a model from the model manager
+        /// </summary>
+        /// <param name="filename">model filename</param>
         public static void Remove(string filename)
         {
             Remove(Get(filename));
         }
 
+        /// <summary>
+        /// Removes a model from the model manager
+        /// </summary>
+        /// <param name="filename">model entry</param>
         public static void Remove(ModelEntry entry)
         {
             if (entry == null) return;
@@ -402,16 +586,27 @@ public static void Remove(ModelEntry entry)
             }
         }
 
+        /// <summary>
+        /// Sets the LLM download progress
+        /// </summary>
+        /// <param name="progress">download progress</param>
         public static void SetModelProgress(float progress)
         {
             modelProgress = progress;
         }
 
+        /// <summary>
+        /// Sets the LORA download progress
+        /// </summary>
+        /// <param name="progress">download progress</param>
         public static void SetLoraProgress(float progress)
         {
             loraProgress = progress;
         }
 
+        /// <summary>
+        /// Serialises and saves the model manager
+        /// </summary>
         public static void Save()
         {
             string json = JsonUtility.ToJson(new LLMManagerStore { modelEntries = modelEntries, downloadOnStart = downloadOnStart }, true);
@@ -419,6 +614,9 @@ public static void Save()
             PlayerPrefs.Save();
         }
 
+        /// <summary>
+        /// Deserialises and loads the model manager
+        /// </summary>
         public static void Load()
         {
             string pref = PlayerPrefs.GetString(LLMManagerPref);
@@ -428,6 +626,9 @@ public static void Load()
             modelEntries = store.modelEntries;
         }
 
+        /// <summary>
+        /// Saves the model manager to disk for the build
+        /// </summary>
         public static void SaveToDisk()
         {
             List<ModelEntry> modelEntriesBuild = new List<ModelEntry>();
@@ -440,6 +641,10 @@ public static void SaveToDisk()
             File.WriteAllText(LLMUnitySetup.LLMManagerPath, json);
         }
 
+        /// <summary>
+        /// Saves the model manager to disk along with models that are not (or can't) be downloaded for the build
+        /// </summary>
+        /// <param name="copyCallback">copy function</param>
         public static void Build(ActionCallback copyCallback)
         {
             SaveToDisk();
diff --git a/Runtime/LLMUnitySetup.cs b/Runtime/LLMUnitySetup.cs
index 0a757b5b..94bca0be 100644
--- a/Runtime/LLMUnitySetup.cs
+++ b/Runtime/LLMUnitySetup.cs
@@ -54,19 +54,19 @@ public DynamicRangeAttribute(string minVariable, string maxVariable, bool intOrF
     }
 
     public class LLMAttribute : PropertyAttribute {}
-    public class LLMAdvancedAttribute : PropertyAttribute {}
     public class LocalRemoteAttribute : PropertyAttribute {}
     public class RemoteAttribute : PropertyAttribute {}
     public class LocalAttribute : PropertyAttribute {}
     public class ModelAttribute : PropertyAttribute {}
-    public class ModelDownloadAttribute : ModelAttribute {}
-    public class ModelDownloadAdvancedAttribute : ModelAdvancedAttribute {}
-    public class ModelAdvancedAttribute : PropertyAttribute {}
     public class ModelExtrasAttribute : PropertyAttribute {}
     public class ChatAttribute : PropertyAttribute {}
-    public class ChatAdvancedAttribute : PropertyAttribute {}
     public class LLMUnityAttribute : PropertyAttribute {}
 
+    public class AdvancedAttribute : PropertyAttribute {}
+    public class LLMAdvancedAttribute : AdvancedAttribute {}
+    public class ModelAdvancedAttribute : AdvancedAttribute {}
+    public class ChatAdvancedAttribute : AdvancedAttribute {}
+
     public class NotImplementedException : Exception
     {
         public NotImplementedException() : base("The method needs to be implemented by subclasses.") {}
@@ -138,6 +138,13 @@ public class LLMUnitySetup
                  ("Llama 3.2 1B", "https://huggingface.co/hugging-quants/Llama-3.2-1B-Instruct-Q4_K_M-GGUF/resolve/main/llama-3.2-1b-instruct-q4_k_m.gguf", null),
                  ("Qwen 2 0.5B", "https://huggingface.co/Qwen/Qwen2-0.5B-Instruct-GGUF/resolve/main/qwen2-0_5b-instruct-q4_k_m.gguf?download=true", null),
              }},
+            {"RAG models", new(string, string, string)[]
+             {
+                 ("All MiniLM L12 v2", "https://huggingface.co/leliuga/all-MiniLM-L12-v2-GGUF/resolve/main/all-MiniLM-L12-v2.Q4_K_M.gguf", null),
+                 ("BGE large en v1.5", "https://huggingface.co/CompendiumLabs/bge-large-en-v1.5-gguf/resolve/main/bge-large-en-v1.5-q4_k_m.gguf", null),
+                 ("BGE base en v1.5", "https://huggingface.co/CompendiumLabs/bge-base-en-v1.5-gguf/resolve/main/bge-base-en-v1.5-q4_k_m.gguf", null),
+                 ("BGE small en v1.5", "https://huggingface.co/CompendiumLabs/bge-small-en-v1.5-gguf/resolve/main/bge-small-en-v1.5-q4_k_m.gguf", null),
+             }},
         };
 
         /// \cond HIDE
diff --git a/Runtime/LLMUtils.cs b/Runtime/LLMUtils.cs
index 75285eee..43681479 100644
--- a/Runtime/LLMUtils.cs
+++ b/Runtime/LLMUtils.cs
@@ -5,7 +5,10 @@
 
 namespace LLMUnity
 {
-    /// \cond HIDE
+    /// @ingroup utils
+    /// <summary>
+    /// Class implementing a basic LLM Exception
+    /// </summary>
     public class LLMException : Exception
     {
         public int ErrorCode { get; private set; }
@@ -16,8 +19,16 @@ public LLMException(string message, int errorCode) : base(message)
         }
     }
 
+    /// @ingroup utils
+    /// <summary>
+    /// Class implementing a basic LLM Destroy Exception
+    /// </summary>
     public class DestroyException : Exception {}
 
+    /// @ingroup utils
+    /// <summary>
+    /// Class representing a LORA asset
+    /// </summary>
     public class LoraAsset
     {
         public string assetPath;
@@ -37,16 +48,28 @@ public static string RuntimePath(string path)
         }
     }
 
+    /// @ingroup utils
+    /// <summary>
+    /// Class representing the LORA manager allowing to convert and retrieve LORA assets to string (for serialisation)
+    /// </summary>
     public class LoraManager
     {
         List<LoraAsset> loras = new List<LoraAsset>();
         public string delimiter = ",";
 
+        /// <summary>
+        /// Clears the LORA assets
+        /// </summary>
         public void Clear()
         {
             loras.Clear();
         }
 
+        /// <summary>
+        /// Searches for a LORA based on the path
+        /// </summary>
+        /// <param name="path">LORA path</param>
+        /// <returns>LORA index</returns>
         public int IndexOf(string path)
         {
             string fullPath = LoraAsset.RuntimePath(path);
@@ -58,23 +81,42 @@ public int IndexOf(string path)
             return -1;
         }
 
+        /// <summary>
+        /// Checks if the provided LORA based on a path exists already in the LORA manager
+        /// </summary>
+        /// <param name="path">LORA path</param>
+        /// <returns>whether the LORA manager contains the LORA</returns>
         public bool Contains(string path)
         {
             return IndexOf(path) != -1;
         }
 
+        /// <summary>
+        /// Adds a LORA with the defined weight
+        /// </summary>
+        /// <param name="path">LORA path</param>
+        /// <param name="weight">LORA weight</param>
         public void Add(string path, float weight = 1)
         {
             if (Contains(path)) return;
             loras.Add(new LoraAsset(path, weight));
         }
 
+        /// <summary>
+        /// Removes a LORA based on its path
+        /// </summary>
+        /// <param name="path">LORA path</param>
         public void Remove(string path)
         {
             int index = IndexOf(path);
             if (index != -1) loras.RemoveAt(index);
         }
 
+        /// <summary>
+        /// Modifies the weight of a LORA
+        /// </summary>
+        /// <param name="path">LORA path</param>
+        /// <param name="weight">LORA weight</param>
         public void SetWeight(string path, float weight)
         {
             int index = IndexOf(path);
@@ -86,6 +128,11 @@ public void SetWeight(string path, float weight)
             loras[index].weight = weight;
         }
 
+        /// <summary>
+        /// Converts strings with the lora paths and weights to entries in the LORA manager
+        /// </summary>
+        /// <param name="loraString">lora paths</param>
+        /// <param name="loraWeightsString">lora weights</param>
         public void FromStrings(string loraString, string loraWeightsString)
         {
             if (string.IsNullOrEmpty(loraString) && string.IsNullOrEmpty(loraWeightsString))
@@ -110,6 +157,10 @@ public void FromStrings(string loraString, string loraWeightsString)
             }
         }
 
+        /// <summary>
+        /// Converts the entries of the LORA manager to strings with the lora paths and weights
+        /// </summary>
+        /// <returns>strings with the lora paths and weights</returns>
         public (string, string) ToStrings()
         {
             string loraString = "";
@@ -127,6 +178,10 @@ public void FromStrings(string loraString, string loraWeightsString)
             return (loraString, loraWeightsString);
         }
 
+        /// <summary>
+        /// Gets the weights of the LORAs in the manager
+        /// </summary>
+        /// <returns>LORA weights</returns>
         public float[] GetWeights()
         {
             float[] weights = new float[loras.Count];
@@ -134,6 +189,10 @@ public float[] GetWeights()
             return weights;
         }
 
+        /// <summary>
+        /// Gets the paths of the LORAs in the manager
+        /// </summary>
+        /// <returns>LORA paths</returns>
         public string[] GetLoras()
         {
             string[] loraPaths = new string[loras.Count];
diff --git a/Runtime/RAG.meta b/Runtime/RAG.meta
new file mode 100644
index 00000000..05b753ad
--- /dev/null
+++ b/Runtime/RAG.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: fd438345162950a4dbd395489c883504
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/Chunking.cs b/Runtime/RAG/Chunking.cs
new file mode 100644
index 00000000..4040e663
--- /dev/null
+++ b/Runtime/RAG/Chunking.cs
@@ -0,0 +1,293 @@
+/// @file
+/// @brief File implementing the chunking functionality
+using System;
+using System.Collections.Generic;
+using System.IO.Compression;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LLMUnity
+{
+    /// @ingroup rag
+    /// <summary>
+    /// Class implementing the chunking functionality
+    /// </summary>
+    [Serializable]
+    public abstract class Chunking : SearchPlugin
+    {
+        protected bool returnChunks = false;
+        protected Dictionary<string, List<int>> dataSplitToPhrases = new Dictionary<string, List<int>>();
+        protected Dictionary<int, int[]> phraseToSentences = new Dictionary<int, int[]>();
+        protected Dictionary<int, int> sentenceToPhrase = new Dictionary<int, int>();
+        protected Dictionary<int, int[]> hexToPhrase = new Dictionary<int, int[]>();
+        protected int nextKey = 0;
+
+        /// <summary>
+        /// Set to true to return chunks or the direct input with the Search function
+        /// </summary>
+        /// <param name="returnChunks">whether to return chunks</param>
+        public void ReturnChunks(bool returnChunks)
+        {
+            this.returnChunks = returnChunks;
+        }
+
+        /// <summary>
+        /// Splits the provided phrase into chunks
+        /// </summary>
+        /// <param name="input">phrase</param>
+        /// <returns>List of start/end indices of the split chunks</returns>
+        public abstract Task<List<(int, int)>> Split(string input);
+
+        /// <summary>
+        /// Retrieves the phrase with the specific id
+        /// </summary>
+        /// <param name="key">phrase id</param>
+        /// <returns>phrase</returns>
+        public override string Get(int key)
+        {
+            StringBuilder phraseBuilder = new StringBuilder();
+            foreach (int sentenceId in phraseToSentences[key])
+            {
+                phraseBuilder.Append(search.Get(sentenceId));
+            }
+            return phraseBuilder.ToString();
+        }
+
+        /// <summary>
+        /// Adds a phrase to the search after splitting it into chunks.
+        /// </summary>
+        /// <param name="inputString">input phrase</param>
+        /// <param name="group">data group to add it to </param>
+        /// <returns>phrase id</returns>
+        public override async Task<int> Add(string inputString, string group = "")
+        {
+            int key = nextKey++;
+            // sentence -> phrase
+            List<int> sentenceIds = new List<int>();
+            foreach ((int startIndex, int endIndex) in await Split(inputString))
+            {
+                string sentenceText = inputString.Substring(startIndex, endIndex - startIndex + 1);
+                int sentenceId = await search.Add(sentenceText, group);
+                sentenceIds.Add(sentenceId);
+
+                sentenceToPhrase[sentenceId] = key;
+            }
+            // phrase -> sentence
+            phraseToSentences[key] = sentenceIds.ToArray();
+
+            // data split -> phrase
+            if (!dataSplitToPhrases.ContainsKey(group)) dataSplitToPhrases[group] = new List<int>(){key};
+            else dataSplitToPhrases[group].Add(key);
+
+            // hex -> phrase
+            int hash = inputString.GetHashCode();
+            if (!hexToPhrase.TryGetValue(hash, out int[] entries)) entries = new int[0];
+            List<int> matchingHash = new List<int>(entries);
+            matchingHash.Add(key);
+
+            hexToPhrase[hash] = matchingHash.ToArray();
+            return key;
+        }
+
+        /// <summary>
+        /// Removes a phrase and the phrase chunks from the search
+        /// </summary>
+        /// <param name="key">phrase id</param>
+        public override void Remove(int key)
+        {
+            if (!phraseToSentences.TryGetValue(key, out int[] sentenceIds)) return;
+            int hash = Get(key).GetHashCode();
+
+            // phrase -> sentence
+            phraseToSentences.Remove(key);
+            foreach (int sentenceId in sentenceIds)
+            {
+                search.Remove(sentenceId);
+                // sentence -> phrase
+                sentenceToPhrase.Remove(sentenceId);
+            }
+
+            // data split -> phrase
+            foreach (var dataSplitPhrases in dataSplitToPhrases.Values) dataSplitPhrases.Remove(key);
+
+            // hex -> phrase
+            if (hexToPhrase.TryGetValue(hash, out int[] phraseIds))
+            {
+                List<int> updatedIds = phraseIds.ToList();
+                updatedIds.Remove(key);
+                if (updatedIds.Count == 0) hexToPhrase.Remove(hash);
+                else hexToPhrase[hash] = updatedIds.ToArray();
+            }
+        }
+
+        /// <summary>
+        /// Removes a phrase and the phrase chunks from the search.
+        /// </summary>
+        /// <param name="inputString">input phrase</param>
+        /// <param name="group">data group to remove it from </param>
+        /// <returns>number of removed phrases</returns>
+        public override int Remove(string inputString, string group = "")
+        {
+            int hash = inputString.GetHashCode();
+            if (!hexToPhrase.TryGetValue(hash, out int[] entries)) return 0;
+            List<int> removeIds = new List<int>();
+            foreach (int key in entries)
+            {
+                if (dataSplitToPhrases[group].Contains(key) && Get(key) == inputString) removeIds.Add(key);
+            }
+            foreach (int removeId in removeIds) Remove(removeId);
+            return removeIds.Count;
+        }
+
+        /// <summary>
+        /// Returns a count of the phrases
+        /// </summary>
+        /// <returns>phrase count</returns>
+        public override int Count()
+        {
+            return phraseToSentences.Count;
+        }
+
+        /// <summary>
+        /// Returns a count of the phrases in a specific data group
+        /// </summary>
+        /// <param name="group">data group</param>
+        /// <returns>phrase count</returns>
+        public override int Count(string group)
+        {
+            if (!dataSplitToPhrases.TryGetValue(group, out List<int> dataSplitPhrases)) return 0;
+            return dataSplitPhrases.Count;
+        }
+
+        /// <summary>
+        /// Allows to do search and retrieve results in batches (incremental search).
+        /// </summary>
+        /// <param name="queryString">search query</param>
+        /// <param name="group">data group to search in</param>
+        /// <returns>incremental search key</returns>
+        public override async Task<int> IncrementalSearch(string queryString, string group = "")
+        {
+            return await search.IncrementalSearch(queryString, group);
+        }
+
+        /// <summary>
+        /// Retrieves the most similar search results in batches (incremental search).
+        /// The phrase/chunk keys and distances are retrieved, as well as a parameter that dictates whether the search is exhausted.
+        /// The returnChunks variable defines whether to return chunks or phrases.
+        /// </summary>
+        /// <param name="fetchKey">incremental search key</param>
+        /// <param name="k">number of results to retrieve</param>
+        /// <returns>
+        /// A tuple containing:
+        /// <list type="bullet">
+        /// <item><description>Array of retrieved keys (`int[]`).</description></item>
+        /// <item><description>Array of distances for each result (`float[]`).</description></item>
+        /// <item><description>`bool` indicating if the search is exhausted.</description></item>
+        /// </list>
+        /// </returns>
+        public override ValueTuple<int[], float[], bool> IncrementalFetchKeys(int fetchKey, int k)
+        {
+            if (returnChunks)
+            {
+                return search.IncrementalFetchKeys(fetchKey, k);
+            }
+            else
+            {
+                List<int> phraseKeys = new List<int>();
+                List<float> distancesList = new List<float>();
+                bool done = false;
+                bool completed;
+                do
+                {
+                    int[] resultKeys;
+                    float[] distancesIter;
+                    (resultKeys, distancesIter, completed) = search.IncrementalFetchKeys(fetchKey, k);
+                    for (int i = 0; i < resultKeys.Length; i++)
+                    {
+                        int phraseId = sentenceToPhrase[resultKeys[i]];
+                        if (phraseKeys.Contains(phraseId)) continue;
+                        phraseKeys.Add(phraseId);
+                        distancesList.Add(distancesIter[i]);
+                        if (phraseKeys.Count() == k)
+                        {
+                            done = true;
+                            break;
+                        }
+                    }
+                    if (completed) break;
+                }
+                while (!done);
+                if (completed) IncrementalSearchComplete(fetchKey);
+                return (phraseKeys.ToArray(), distancesList.ToArray(), completed);
+            }
+        }
+
+        /// <summary>
+        /// Retrieves the most similar search results in batches (incremental search).
+        /// The phrases/chunks and their distances are retrieved, as well as a parameter that dictates whether the search is exhausted.
+        /// The returnChunks variable defines whether to return chunks or phrases.
+        /// </summary>
+        /// <param name="fetchKey">incremental search key</param>
+        /// <param name="k">number of results to retrieve</param>
+        /// <returns>
+        /// A tuple containing:
+        /// <list type="bullet">
+        /// <item><description>Array of retrieved phrases/chunks (`string[]`).</description></item>
+        /// <item><description>Array of distances for each result (`float[]`).</description></item>
+        /// <item><description>`bool` indicating if the search is exhausted.</description></item>
+        /// </list>
+        /// </returns>
+        public override ValueTuple<string[], float[], bool> IncrementalFetch(int fetchKey, int k)
+        {
+            (int[] resultKeys, float[] distances, bool completed) = IncrementalFetchKeys(fetchKey, k);
+            string[] results = new string[resultKeys.Length];
+            for (int i = 0; i < resultKeys.Length; i++)
+            {
+                if (returnChunks) results[i] = search.Get(resultKeys[i]);
+                else results[i] = Get(resultKeys[i]);
+            }
+            return (results, distances, completed);
+        }
+
+        /// <summary>
+        /// Completes the search and clears the cached results for an incremental search
+        /// </summary>
+        /// <param name="fetchKey">incremental search key</param>
+        public override void IncrementalSearchComplete(int fetchKey)
+        {
+            search.IncrementalSearchComplete(fetchKey);
+        }
+
+        /// <summary>
+        /// Clears the object and the associated search object
+        /// </summary>
+        public override void Clear()
+        {
+            nextKey = 0;
+            dataSplitToPhrases.Clear();
+            phraseToSentences.Clear();
+            sentenceToPhrase.Clear();
+            hexToPhrase.Clear();
+            search.Clear();
+        }
+
+        protected override void SaveInternal(ZipArchive archive)
+        {
+            ArchiveSaver.Save(archive, dataSplitToPhrases, GetSavePath("dataSplitToPhrases"));
+            ArchiveSaver.Save(archive, phraseToSentences, GetSavePath("phraseToSentences"));
+            ArchiveSaver.Save(archive, sentenceToPhrase, GetSavePath("sentenceToPhrase"));
+            ArchiveSaver.Save(archive, hexToPhrase, GetSavePath("hexToPhrase"));
+            ArchiveSaver.Save(archive, nextKey, GetSavePath("nextKey"));
+        }
+
+        protected override void LoadInternal(ZipArchive archive)
+        {
+            dataSplitToPhrases = ArchiveSaver.Load<Dictionary<string, List<int>>>(archive, GetSavePath("dataSplitToPhrases"));
+            phraseToSentences = ArchiveSaver.Load<Dictionary<int, int[]>>(archive, GetSavePath("phraseToSentences"));
+            sentenceToPhrase = ArchiveSaver.Load<Dictionary<int, int>>(archive, GetSavePath("sentenceToPhrase"));
+            hexToPhrase = ArchiveSaver.Load<Dictionary<int, int[]>>(archive, GetSavePath("hexToPhrase"));
+            nextKey = ArchiveSaver.Load<int>(archive, GetSavePath("nextKey"));
+        }
+    }
+}
diff --git a/Runtime/RAG/Chunking.cs.meta b/Runtime/RAG/Chunking.cs.meta
new file mode 100644
index 00000000..f427c6fc
--- /dev/null
+++ b/Runtime/RAG/Chunking.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 53b6e1e6db0e47a1f8fb1e06835ed543
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/DBSearch.cs b/Runtime/RAG/DBSearch.cs
new file mode 100644
index 00000000..91265947
--- /dev/null
+++ b/Runtime/RAG/DBSearch.cs
@@ -0,0 +1,115 @@
+/// @file
+/// @brief File implementing the vector database search.
+using System;
+using System.Collections.Generic;
+using Cloud.Unum.USearch;
+using System.IO.Compression;
+using UnityEngine;
+
+namespace LLMUnity
+{
+    /// @ingroup rag
+    /// <summary>
+    /// Class implementing a search with a vector database.
+    /// The search results are retrieved with Approximate Nearest Neighbor (ANN) which is much faster that SimpleSearch.
+    /// </summary>
+    [DefaultExecutionOrder(-2)]
+    public class DBSearch : SearchMethod
+    {
+        protected USearchIndex index;
+        /// <summary> toggle to show/hide advanced options in the GameObject </summary>
+        [HideInInspector] public bool advancedOptions = false;
+        /// <summary> The quantisation type used for vector data during indexing. </summary>
+        [ModelAdvanced] public ScalarKind quantization = ScalarKind.Float16;
+        /// <summary> The metric kind used for distance calculation between vectors. </summary>
+        [ModelAdvanced] public MetricKind metricKind = MetricKind.Cos;
+        /// <summary> The connectivity parameter limits the connections-per-node in the graph. </summary>
+        [ModelAdvanced] public ulong connectivity = 32;
+        /// <summary> The expansion factor used for index construction when adding vectors. </summary>
+        [ModelAdvanced] public ulong expansionAdd = 40;
+        /// <summary> The expansion factor used for index construction during search operations. </summary>
+        [ModelAdvanced] public ulong expansionSearch = 16;
+
+        private Dictionary<int, (float[], string, List<int>)> incrementalSearchCache = new Dictionary<int, (float[], string, List<int>)>();
+
+        /// \cond HIDE
+        public new void Awake()
+        {
+            base.Awake();
+            if (!enabled) return;
+            InitIndex();
+        }
+
+        public void InitIndex()
+        {
+            index = new USearchIndex(metricKind, quantization, (ulong)llmEmbedder.llm.embeddingLength, connectivity, expansionAdd, expansionSearch, false);
+        }
+
+        protected override void AddInternal(int key, float[] embedding)
+        {
+            index.Add((ulong)key, embedding);
+        }
+
+        protected override void RemoveInternal(int key)
+        {
+            index.Remove((ulong)key);
+        }
+
+        protected int[] UlongToInt(ulong[] keys)
+        {
+            int[] intKeys = new int[keys.Length];
+            for (int i = 0; i < keys.Length; i++) intKeys[i] = (int)keys[i];
+            return intKeys;
+        }
+
+        public override int IncrementalSearch(float[] embedding, string group = "")
+        {
+            int key = nextIncrementalSearchKey++;
+            incrementalSearchCache[key] = (embedding, group, new List<int>());
+            return key;
+        }
+
+        public override ValueTuple<int[], float[], bool> IncrementalFetchKeys(int fetchKey, int k)
+        {
+            if (!incrementalSearchCache.ContainsKey(fetchKey)) throw new Exception($"There is no IncrementalSearch cached with this key: {fetchKey}");
+
+            (float[] embedding, string group, List<int> seenKeys) = incrementalSearchCache[fetchKey];
+
+            if (!dataSplits.TryGetValue(group, out List<int> dataSplit)) return (new int[0], new float[0], true);
+            if (dataSplit.Count == 0) return (new int[0], new float[0], true);
+
+            Func<int, int> filter = (int key) => !dataSplit.Contains(key) || seenKeys.Contains(key) ? 0 : 1;
+            index.Search(embedding, k, out ulong[] keys, out float[] distances, filter);
+            int[] intKeys = UlongToInt(keys);
+            incrementalSearchCache[fetchKey].Item3.AddRange(intKeys);
+
+            bool completed = intKeys.Length < k || seenKeys.Count == Count(group);
+            if (completed) IncrementalSearchComplete(fetchKey);
+            return (intKeys, distances, completed);
+        }
+
+        public override void IncrementalSearchComplete(int fetchKey)
+        {
+            incrementalSearchCache.Remove(fetchKey);
+        }
+
+        protected override void SaveInternal(ZipArchive archive)
+        {
+            index.Save(archive);
+        }
+
+        protected override void LoadInternal(ZipArchive archive)
+        {
+            index.Load(archive);
+        }
+
+        protected override void ClearInternal()
+        {
+            index.Dispose();
+            InitIndex();
+            incrementalSearchCache.Clear();
+        }
+
+        /// \endcond
+    }
+}
diff --git a/Runtime/RAG/DBSearch.cs.meta b/Runtime/RAG/DBSearch.cs.meta
new file mode 100644
index 00000000..aee765d6
--- /dev/null
+++ b/Runtime/RAG/DBSearch.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f8c6492f8c97ab9a09b0eb0f93a158da
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/RAG.cs b/Runtime/RAG/RAG.cs
new file mode 100644
index 00000000..55988175
--- /dev/null
+++ b/Runtime/RAG/RAG.cs
@@ -0,0 +1,126 @@
+/// @file
+/// @brief File implementing the Retrieval Augmented Generation (RAG) system.
+using System;
+using System.IO.Compression;
+using System.Threading.Tasks;
+using UnityEditor;
+using UnityEngine;
+
+namespace LLMUnity
+{
+    /// <summary>
+    /// Search methods implemented in LLMUnity
+    /// </summary>
+    public enum SearchMethods
+    {
+        DBSearch,
+        SimpleSearch,
+    }
+
+    public class NoChunking {}
+
+    /// <summary>
+    /// Chunking methods implemented in LLMUnity
+    /// </summary>
+    public enum ChunkingMethods
+    {
+        NoChunking,
+        TokenSplitter,
+        WordSplitter,
+        SentenceSplitter
+    }
+
+    /// @ingroup rag
+    /// <summary>
+    /// Class implementing a Retrieval Augmented Generation (RAG) system based on a search method and an optional chunking method.
+    /// </summary>
+    [Serializable]
+    public class RAG : Searchable
+    {
+        public SearchMethods searchType = SearchMethods.SimpleSearch;
+        public SearchMethod search;
+        public ChunkingMethods chunkingType = ChunkingMethods.NoChunking;
+        public Chunking chunking;
+
+        /// <summary>
+        /// Constructs the Retrieval Augmented Generation (RAG) system based on the provided search and chunking method.
+        /// </summary>
+        /// <param name="searchMethod">search method</param>
+        /// <param name="chunkingMethod">chunking method for splitting the search entries</param>
+        /// <param name="llm">LLM to use for the search method</param>
+        public void Init(SearchMethods searchMethod = SearchMethods.SimpleSearch, ChunkingMethods chunkingMethod = ChunkingMethods.NoChunking, LLM llm = null)
+        {
+            searchType = searchMethod;
+            chunkingType = chunkingMethod;
+            UpdateGameObjects();
+            search.SetLLM(llm);
+        }
+
+        /// <summary>
+        /// Set to true to return chunks or the direct input with the Search function
+        /// </summary>
+        /// <param name="returnChunks">whether to return chunks</param>
+        public void ReturnChunks(bool returnChunks)
+        {
+            if (chunking != null) chunking.ReturnChunks(returnChunks);
+        }
+
+        /// \cond HIDE
+        protected void ConstructSearch()
+        {
+            search = ConstructComponent<SearchMethod>(Type.GetType("LLMUnity." + searchType.ToString()), (previous, current) => current.llmEmbedder.llm = previous.llmEmbedder.llm);
+            if (chunking != null) chunking.SetSearch(search);
+        }
+
+        protected void ConstructChunking()
+        {
+            Type type = null;
+            if (chunkingType != ChunkingMethods.NoChunking) type = Type.GetType("LLMUnity." + chunkingType.ToString());
+            chunking = ConstructComponent<Chunking>(type);
+            if (chunking != null) chunking.SetSearch(search);
+        }
+
+        public override void UpdateGameObjects()
+        {
+            if (this == null) return;
+            ConstructSearch();
+            ConstructChunking();
+        }
+
+        protected Searchable GetSearcher()
+        {
+            if (chunking != null) return chunking;
+            if (search != null) return search;
+            throw new Exception("The search GameObject is null");
+        }
+
+#if UNITY_EDITOR
+        private void OnValidateUpdate()
+        {
+            EditorApplication.delayCall -= OnValidateUpdate;
+            UpdateGameObjects();
+        }
+
+        public virtual void OnValidate()
+        {
+            if (!Application.isPlaying) EditorApplication.delayCall += OnValidateUpdate;
+        }
+
+#endif
+
+        public override string Get(int key) { return GetSearcher().Get(key); }
+        public override async Task<int> Add(string inputString, string group = "") { return await GetSearcher().Add(inputString, group); }
+        public override int Remove(string inputString, string group = "") { return GetSearcher().Remove(inputString, group); }
+        public override void Remove(int key) { GetSearcher().Remove(key); }
+        public override int Count() { return GetSearcher().Count(); }
+        public override int Count(string group) { return GetSearcher().Count(group); }
+        public override void Clear() { GetSearcher().Clear(); }
+        public override async Task<int> IncrementalSearch(string queryString, string group = "") { return await GetSearcher().IncrementalSearch(queryString, group);}
+        public override (string[], float[], bool) IncrementalFetch(int fetchKey, int k) { return GetSearcher().IncrementalFetch(fetchKey, k);}
+        public override (int[], float[], bool) IncrementalFetchKeys(int fetchKey, int k) { return GetSearcher().IncrementalFetchKeys(fetchKey, k);}
+        public override void IncrementalSearchComplete(int fetchKey) { GetSearcher().IncrementalSearchComplete(fetchKey);}
+        public override void Save(ZipArchive archive) { GetSearcher().Save(archive); }
+        public override void Load(ZipArchive archive) { GetSearcher().Load(archive); }
+        /// \endcond
+    }
+}
diff --git a/Runtime/RAG/RAG.cs.meta b/Runtime/RAG/RAG.cs.meta
new file mode 100644
index 00000000..62394035
--- /dev/null
+++ b/Runtime/RAG/RAG.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a2496546d1575771597fc8cbdd0d852d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/Search.cs b/Runtime/RAG/Search.cs
new file mode 100644
index 00000000..50383b5b
--- /dev/null
+++ b/Runtime/RAG/Search.cs
@@ -0,0 +1,538 @@
+/// @file
+/// @brief File implementing the search functionality
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Threading.Tasks;
+using UnityEditor;
+using UnityEngine;
+
+/// @defgroup rag RAG
+namespace LLMUnity
+{
+    /// @ingroup rag
+    /// <summary>
+    /// Class implementing the search template
+    /// </summary>
+    [DefaultExecutionOrder(-2)]
+    public abstract class Searchable : MonoBehaviour
+    {
+        /// <summary>
+        /// Retrieves the phrase with the specific id
+        /// </summary>
+        /// <param name="key">phrase id</param>
+        /// <returns>phrase</returns>
+        public abstract string Get(int key);
+
+        /// <summary>
+        /// Adds a phrase to the search.
+        /// </summary>
+        /// <param name="inputString">input phrase</param>
+        /// <param name="group">data group to add it to </param>
+        /// <returns>phrase id</returns>
+        public abstract Task<int> Add(string inputString, string group = "");
+
+        /// <summary>
+        /// Removes a phrase from the search.
+        /// </summary>
+        /// <param name="inputString">input phrase</param>
+        /// <param name="group">data group to remove it from </param>
+        /// <returns>number of removed entries/returns>
+        public abstract int Remove(string inputString, string group = "");
+
+        /// <summary>
+        /// Removes a phrase from the search.
+        /// </summary>
+        /// <param name="key">phrase id</param>
+        public abstract void Remove(int key);
+
+        /// <summary>
+        /// Returns a count of the phrases
+        /// </summary>
+        /// <returns>phrase count</returns>
+        public abstract int Count();
+
+        /// <summary>
+        /// Returns a count of the phrases in a specific data group
+        /// </summary>
+        /// <param name="group">data group</param>
+        /// <returns>phrase count</returns>
+        public abstract int Count(string group);
+
+        /// <summary>
+        /// Clears the search object
+        /// </summary>
+        public abstract void Clear();
+
+        /// <summary>
+        /// Allows to do search and retrieve results in batches (incremental search).
+        /// </summary>
+        /// <param name="queryString">search query</param>
+        /// <param name="group">data group to search in</param>
+        /// <returns>incremental search key</returns>
+        public abstract Task<int> IncrementalSearch(string queryString, string group = "");
+
+        /// <summary>
+        /// Retrieves the most similar search results in batches (incremental search).
+        /// The phrase keys and distances are retrieved, as well as a parameter that dictates whether the search is exhausted.
+        /// </summary>
+        /// <param name="fetchKey">incremental search key</param>
+        /// <param name="k">number of results to retrieve</param>
+        /// <returns>
+        /// A tuple containing:
+        /// <list type="bullet">
+        /// <item><description>Array of retrieved keys (`int[]`).</description></item>
+        /// <item><description>Array of distances for each result (`float[]`).</description></item>
+        /// <item><description>`bool` indicating if the search is exhausted.</description></item>
+        /// </list>
+        /// </returns>
+        public abstract ValueTuple<int[], float[], bool> IncrementalFetchKeys(int fetchKey, int k);
+
+        /// <summary>
+        /// Completes the search and clears the cached results for an incremental search
+        /// </summary>
+        /// <param name="fetchKey">incremental search key</param>
+        public abstract void IncrementalSearchComplete(int fetchKey);
+
+        /// <summary>
+        /// Search for similar results to the provided query.
+        /// The most similar results and their distances (dissimilarity) to the query are retrieved.
+        /// </summary>
+        /// <param name="queryString">query</param>
+        /// <param name="k">number of results to retrieve</param>
+        /// <param name="group">data group to search in</param>
+        /// <returns>
+        /// A tuple containing:
+        /// <list type="bullet">
+        /// <item><description>Array of retrieved results (`string[]`).</description></item>
+        /// <item><description>Array of distances for each result (`float[]`).</description></item>
+        /// <item><description>`bool` indicating if the search is exhausted.</description></item>
+        /// </list>
+        /// </returns>
+        public async Task<(string[], float[])> Search(string queryString, int k, string group = "")
+        {
+            int fetchKey = await IncrementalSearch(queryString, group);
+            (string[] phrases, float[] distances, bool completed) = IncrementalFetch(fetchKey, k);
+            if (!completed) IncrementalSearchComplete(fetchKey);
+            return (phrases, distances);
+        }
+
+        /// <summary>
+        /// Retrieves the most similar search results in batches (incremental search).
+        /// The most similar results and their distances (dissimilarity) to the query are retrieved as well as a parameter that dictates whether the search is exhausted.
+        /// </summary>
+        /// <param name="fetchKey">incremental search key</param>
+        /// <param name="k">number of results to retrieve</param>
+        /// <returns>
+        /// A tuple containing:
+        /// <list type="bullet">
+        /// <item><description>Array of retrieved results (`string[]`).</description></item>
+        /// <item><description>Array of distances for each result (`float[]`).</description></item>
+        /// <item><description>`bool` indicating if the search is exhausted.</description></item>
+        /// </list>
+        /// </returns>
+        public virtual ValueTuple<string[], float[], bool> IncrementalFetch(int fetchKey, int k)
+        {
+            (int[] resultKeys, float[] distances, bool completed) = IncrementalFetchKeys(fetchKey, k);
+            string[] results = new string[resultKeys.Length];
+            for (int i = 0; i < resultKeys.Length; i++) results[i] = Get(resultKeys[i]);
+            return (results, distances, completed);
+        }
+
+        /// <summary>
+        /// Saves the state of the search object.
+        /// </summary>
+        /// <param name="archive">file to save to</param>
+        public void Save(string filePath)
+        {
+            try
+            {
+                string path = LLMUnitySetup.GetAssetPath(filePath);
+                ArchiveSaver.Save(path, Save);
+            }
+            catch (Exception e)
+            {
+                LLMUnitySetup.LogError($"File {filePath} could not be saved due to {e.GetType()}: {e.Message}");
+            }
+        }
+
+        /// <summary>
+        /// Loads the state of the search object.
+        /// </summary>
+        /// <param name="archive">file to load from</param>
+        public async Task<bool> Load(string filePath)
+        {
+            try
+            {
+                await LLMUnitySetup.AndroidExtractAsset(filePath, true);
+                string path = LLMUnitySetup.GetAssetPath(filePath);
+                if (!File.Exists(path)) return false;
+                ArchiveSaver.Load(path, Load);
+            }
+            catch (Exception e)
+            {
+                LLMUnitySetup.LogError($"File {filePath} could not be loaded due to {e.GetType()}: {e.Message}");
+                return false;
+            }
+            return true;
+        }
+
+        /// \cond HIDE
+        public abstract void Save(ZipArchive archive);
+        public abstract void Load(ZipArchive archive);
+        public virtual string GetSavePath(string name)
+        {
+            return Path.Combine(GetType().Name, name);
+        }
+
+        public virtual void UpdateGameObjects() {}
+
+        protected T ConstructComponent<T>(Type type, Action<T, T> copyAction = null) where T : Component
+        {
+            T Construct(Type type)
+            {
+                if (type == null) return null;
+                T newComponent = (T)gameObject.AddComponent(type);
+                if (newComponent is Searchable searchable) searchable.UpdateGameObjects();
+                return newComponent;
+            }
+
+            T component = (T)gameObject.GetComponent(typeof(T));
+            T newComponent;
+            if (component == null)
+            {
+                newComponent = Construct(type);
+            }
+            else
+            {
+                if (component.GetType() == type)
+                {
+                    newComponent = component;
+                }
+                else
+                {
+                    newComponent = Construct(type);
+                    if (type != null) copyAction?.Invoke(component, newComponent);
+#if UNITY_EDITOR
+                    DestroyImmediate(component);
+#else
+                    Destroy(component);
+#endif
+                }
+            }
+            return newComponent;
+        }
+
+        public virtual void Awake()
+        {
+            UpdateGameObjects();
+        }
+
+#if UNITY_EDITOR
+        public virtual void Reset()
+        {
+            if (!Application.isPlaying) EditorApplication.update += UpdateGameObjects;
+        }
+
+        public virtual void OnDestroy()
+        {
+            if (!Application.isPlaying) EditorApplication.update -= UpdateGameObjects;
+        }
+
+#endif
+        /// \endcond
+    }
+
+    /// @ingroup rag
+    /// <summary>
+    /// Class implementing the search method template
+    /// </summary>
+    public abstract class SearchMethod : Searchable
+    {
+        public LLMEmbedder llmEmbedder;
+
+        protected int nextKey = 0;
+        protected int nextIncrementalSearchKey = 0;
+        protected SortedDictionary<int, string> data = new SortedDictionary<int, string>();
+        protected SortedDictionary<string, List<int>> dataSplits = new SortedDictionary<string, List<int>>();
+
+        protected LLM llm;
+
+        protected abstract void AddInternal(int key, float[] embedding);
+        protected abstract void RemoveInternal(int key);
+        protected abstract void ClearInternal();
+        protected abstract void SaveInternal(ZipArchive archive);
+        protected abstract void LoadInternal(ZipArchive archive);
+
+        /// <summary>
+        /// Sets the LLM for encoding the search entries
+        /// </summary>
+        /// <param name="llm"></param>
+        public void SetLLM(LLM llm)
+        {
+            this.llm = llm;
+            if (llmEmbedder != null) llmEmbedder.llm = llm;
+        }
+
+        /// <summary>
+        /// Orders the entries in the searchList according to their similarity to the provided query.
+        /// The entries and distances (dissimilarity) to the query are returned in decreasing order of similarity.
+        /// </summary>
+        /// <param name="queryString">query</param>
+        /// <param name="searchList">entries to order based on similarity</param>
+        /// <returns>
+        /// A tuple containing:
+        /// <list type="bullet">
+        /// <item><description>Array of entries (`string[]`).</description></item>
+        /// <item><description>Array of distances for each result (`float[]`).</description></item>
+        /// </list>
+        /// </returns>
+        public async Task<(string[], float[])> SearchFromList(string query, string[] searchList)
+        {
+            float[] embedding = await Encode(query);
+            float[][] embeddingsList = new float[searchList.Length][];
+            for (int i = 0; i < searchList.Length; i++) embeddingsList[i] = await Encode(searchList[i]);
+
+            float[] unsortedDistances = InverseDotProduct(embedding, embeddingsList);
+            List<(string, float)> sortedLists = searchList.Zip(unsortedDistances, (first, second) => (first, second))
+                .OrderBy(item => item.Item2)
+                .ToList();
+
+            string[] results = new string[sortedLists.Count];
+            float[] distances = new float[sortedLists.Count];
+            for (int i = 0; i < sortedLists.Count; i++)
+            {
+                results[i] = sortedLists[i].Item1;
+                distances[i] = sortedLists[i].Item2;
+            }
+            return (results.ToArray(), distances.ToArray());
+        }
+
+        /// \cond HIDE
+        public static float DotProduct(float[] vector1, float[] vector2)
+        {
+            if (vector1 == null || vector2 == null) throw new ArgumentNullException("Vectors cannot be null");
+            if (vector1.Length != vector2.Length) throw new ArgumentException("Vector lengths must be equal for dot product calculation");
+            float result = 0;
+            for (int i = 0; i < vector1.Length; i++)
+            {
+                result += vector1[i] * vector2[i];
+            }
+            return result;
+        }
+
+        public static float InverseDotProduct(float[] vector1, float[] vector2)
+        {
+            return 1 - DotProduct(vector1, vector2);
+        }
+
+        public static float[] InverseDotProduct(float[] vector1, float[][] vector2)
+        {
+            float[] results = new float[vector2.Length];
+            for (int i = 0; i < vector2.Length; i++)
+            {
+                results[i] = InverseDotProduct(vector1, vector2[i]);
+            }
+            return results;
+        }
+
+        public virtual async Task<float[]> Encode(string inputString)
+        {
+            return (await llmEmbedder.Embeddings(inputString)).ToArray();
+        }
+
+        public virtual async Task<List<int>> Tokenize(string query, Callback<List<int>> callback = null)
+        {
+            return await llmEmbedder.Tokenize(query, callback);
+        }
+
+        public async Task<string> Detokenize(List<int> tokens, Callback<string> callback = null)
+        {
+            return await llmEmbedder.Detokenize(tokens, callback);
+        }
+
+        public override string Get(int key)
+        {
+            if (data.TryGetValue(key, out string result)) return result;
+            return null;
+        }
+
+        public override async Task<int> Add(string inputString, string group = "")
+        {
+            int key = nextKey++;
+            AddInternal(key, await Encode(inputString));
+
+            data[key] = inputString;
+            if (!dataSplits.ContainsKey(group)) dataSplits[group] = new List<int>(){key};
+            else dataSplits[group].Add(key);
+            return key;
+        }
+
+        public override void Clear()
+        {
+            data.Clear();
+            dataSplits.Clear();
+            ClearInternal();
+            nextKey = 0;
+            nextIncrementalSearchKey = 0;
+        }
+
+        protected bool RemoveEntry(int key)
+        {
+            bool removed = data.Remove(key);
+            if (removed) RemoveInternal(key);
+            return removed;
+        }
+
+        public override void Remove(int key)
+        {
+            if (RemoveEntry(key))
+            {
+                foreach (var dataSplit in dataSplits.Values) dataSplit.Remove(key);
+            }
+        }
+
+        public override int Remove(string inputString, string group = "")
+        {
+            if (!dataSplits.TryGetValue(group, out List<int> dataSplit)) return 0;
+            List<int> removeIds = new List<int>();
+            foreach (int key in dataSplit)
+            {
+                if (Get(key) == inputString) removeIds.Add(key);
+            }
+            foreach (int key in removeIds)
+            {
+                if (RemoveEntry(key)) dataSplit.Remove(key);
+            }
+            return removeIds.Count;
+        }
+
+        public override int Count()
+        {
+            return data.Count;
+        }
+
+        public override int Count(string group)
+        {
+            if (!dataSplits.TryGetValue(group, out List<int> dataSplit)) return 0;
+            return dataSplit.Count;
+        }
+
+        public override async Task<int> IncrementalSearch(string queryString, string group = "")
+        {
+            return IncrementalSearch(await Encode(queryString), group);
+        }
+
+        public override void Save(ZipArchive archive)
+        {
+            ArchiveSaver.Save(archive, data, GetSavePath("data"));
+            ArchiveSaver.Save(archive, dataSplits, GetSavePath("dataSplits"));
+            ArchiveSaver.Save(archive, nextKey, GetSavePath("nextKey"));
+            ArchiveSaver.Save(archive, nextIncrementalSearchKey, GetSavePath("nextIncrementalSearchKey"));
+            SaveInternal(archive);
+        }
+
+        public override void Load(ZipArchive archive)
+        {
+            data = ArchiveSaver.Load<SortedDictionary<int, string>>(archive, GetSavePath("data"));
+            dataSplits = ArchiveSaver.Load<SortedDictionary<string, List<int>>>(archive, GetSavePath("dataSplits"));
+            nextKey = ArchiveSaver.Load<int>(archive, GetSavePath("nextKey"));
+            nextIncrementalSearchKey = ArchiveSaver.Load<int>(archive, GetSavePath("nextIncrementalSearchKey"));
+            LoadInternal(archive);
+        }
+
+        public override void UpdateGameObjects()
+        {
+            if (this == null || llmEmbedder != null) return;
+            llmEmbedder = ConstructComponent<LLMEmbedder>(typeof(LLMEmbedder), (previous, current) => current.llm = previous.llm);
+        }
+
+        public abstract int IncrementalSearch(float[] embedding, string group = "");
+        /// \endcond
+    }
+
+    /// @ingroup rag
+    /// <summary>
+    /// Class implementing the search plugin template used e.g. in chunking
+    /// </summary>
+    public abstract class SearchPlugin : Searchable
+    {
+        protected SearchMethod search;
+
+        /// <summary>
+        /// Sets the search method of the plugin
+        /// </summary>
+        /// <param name="llm"></param>
+        public void SetSearch(SearchMethod search)
+        {
+            this.search = search;
+        }
+
+        /// \cond HIDE
+        protected abstract void SaveInternal(ZipArchive archive);
+        protected abstract void LoadInternal(ZipArchive archive);
+
+        public override void Save(ZipArchive archive)
+        {
+            search.Save(archive);
+            SaveInternal(archive);
+        }
+
+        public override void Load(ZipArchive archive)
+        {
+            search.Load(archive);
+            LoadInternal(archive);
+        }
+
+        /// \endcond
+    }
+
+    /// \cond HIDE
+    public class ArchiveSaver
+    {
+        public delegate void ArchiveSaverCallback(ZipArchive archive);
+
+        public static void Save(string filePath, ArchiveSaverCallback callback)
+        {
+            using (FileStream stream = new FileStream(filePath, FileMode.Create))
+            using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Create))
+            {
+                callback(archive);
+            }
+        }
+
+        public static void Load(string filePath, ArchiveSaverCallback callback)
+        {
+            using (FileStream stream = new FileStream(filePath, FileMode.Open))
+            using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Read))
+            {
+                callback(archive);
+            }
+        }
+
+        public static void Save(ZipArchive archive, object saveObject, string name)
+        {
+            ZipArchiveEntry mainEntry = archive.CreateEntry(name);
+            using (Stream entryStream = mainEntry.Open())
+            {
+                BinaryFormatter formatter = new BinaryFormatter();
+                formatter.Serialize(entryStream, saveObject);
+            }
+        }
+
+        public static T Load<T>(ZipArchive archive, string name)
+        {
+            ZipArchiveEntry baseEntry = archive.GetEntry(name);
+            if (baseEntry == null) throw new Exception($"No entry with name {name} was found");
+            using (Stream entryStream = baseEntry.Open())
+            {
+                BinaryFormatter formatter = new BinaryFormatter();
+                return (T)formatter.Deserialize(entryStream);
+            }
+        }
+    }
+    /// \endcond
+}
diff --git a/Runtime/RAG/Search.cs.meta b/Runtime/RAG/Search.cs.meta
new file mode 100644
index 00000000..4d857653
--- /dev/null
+++ b/Runtime/RAG/Search.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 98f7725a31f2e7d8485b2cdf541fc8d4
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/SentenceSplitter.cs b/Runtime/RAG/SentenceSplitter.cs
new file mode 100644
index 00000000..75507b7b
--- /dev/null
+++ b/Runtime/RAG/SentenceSplitter.cs
@@ -0,0 +1,53 @@
+/// @file
+/// @brief File implementing a sentence-based splitter
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using System.Linq;
+
+namespace LLMUnity
+{
+    /// @ingroup rag
+    /// <summary>
+    /// Class implementing a sentence-based splitter
+    /// </summary>
+    [Serializable]
+    public class SentenceSplitter : Chunking
+    {
+        public const string DefaultDelimiters = ".!:;?\n\r";
+        /// <summary> delimiters used to split the phrases </summary>
+        public char[] delimiters = DefaultDelimiters.ToCharArray();
+
+        /// <summary>
+        /// Splits the provided phrase into chunks according to delimiters (defined in the delimiters variable)
+        /// </summary>
+        /// <param name="input">phrase</param>
+        /// <returns>List of start/end indices of the split chunks</returns>
+        public override async Task<List<(int, int)>> Split(string input)
+        {
+            List<(int, int)> indices = new List<(int, int)>();
+            await Task.Run(() => {
+                int startIndex = 0;
+                bool seenChar = false;
+                for (int i = 0; i < input.Length; i++)
+                {
+                    bool isDelimiter = delimiters.Contains(input[i]);
+                    if (isDelimiter)
+                    {
+                        while ((i < input.Length - 1) && (delimiters.Contains(input[i + 1]) || char.IsWhiteSpace(input[i + 1]))) i++;
+                    }
+                    else
+                    {
+                        if (!seenChar) seenChar = !char.IsWhiteSpace(input[i]);
+                    }
+                    if ((i == input.Length - 1) || (isDelimiter && seenChar))
+                    {
+                        indices.Add((startIndex, i));
+                        startIndex = i + 1;
+                    }
+                }
+            });
+            return indices;
+        }
+    }
+}
diff --git a/Runtime/RAG/SentenceSplitter.cs.meta b/Runtime/RAG/SentenceSplitter.cs.meta
new file mode 100644
index 00000000..6102827f
--- /dev/null
+++ b/Runtime/RAG/SentenceSplitter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 354c2418b0d6913efbfb73dccd540d23
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/SimpleSearch.cs b/Runtime/RAG/SimpleSearch.cs
new file mode 100644
index 00000000..8d97d645
--- /dev/null
+++ b/Runtime/RAG/SimpleSearch.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.IO.Compression;
+using UnityEngine;
+
+namespace LLMUnity
+{
+    /// @ingroup rag
+    /// <summary>
+    /// Class implementing a simple search that compares the enconding of the search query with all the search entries (brute-force).
+    /// </summary>
+    [DefaultExecutionOrder(-2)]
+    public class SimpleSearch : SearchMethod
+    {
+        /// \cond HIDE
+        protected SortedDictionary<int, float[]> embeddings = new SortedDictionary<int, float[]>();
+        protected Dictionary<int, List<(int, float)>> incrementalSearchCache = new Dictionary<int, List<(int, float)>>();
+
+        protected override void AddInternal(int key, float[] embedding)
+        {
+            embeddings[key] = embedding;
+        }
+
+        protected override void RemoveInternal(int key)
+        {
+            embeddings.Remove(key);
+        }
+
+        public override int IncrementalSearch(float[] embedding, string group = "")
+        {
+            int key = nextIncrementalSearchKey++;
+
+            List<(int, float)> sortedLists = new List<(int, float)>();
+            if (dataSplits.TryGetValue(group, out List<int> dataSplit))
+            {
+                if (dataSplit.Count >= 0)
+                {
+                    float[][] embeddingsSplit = new float[dataSplit.Count][];
+                    for (int i = 0; i < dataSplit.Count; i++) embeddingsSplit[i] = embeddings[dataSplit[i]];
+
+                    float[] unsortedDistances = InverseDotProduct(embedding, embeddingsSplit);
+                    sortedLists = dataSplit.Zip(unsortedDistances, (first, second) => (first, second))
+                        .OrderBy(item => item.Item2)
+                        .ToList();
+                }
+            }
+            incrementalSearchCache[key] = sortedLists;
+            return key;
+        }
+
+        public override ValueTuple<int[], float[], bool> IncrementalFetchKeys(int fetchKey, int k)
+        {
+            if (!incrementalSearchCache.ContainsKey(fetchKey)) throw new Exception($"There is no IncrementalSearch cached with this key: {fetchKey}");
+
+            bool completed;
+            List<(int, float)> sortedLists;
+            if (k == -1)
+            {
+                sortedLists = incrementalSearchCache[fetchKey];
+                completed = true;
+            }
+            else
+            {
+                int getK = Math.Min(k, incrementalSearchCache[fetchKey].Count);
+                sortedLists = incrementalSearchCache[fetchKey].GetRange(0, getK);
+                incrementalSearchCache[fetchKey].RemoveRange(0, getK);
+                completed = incrementalSearchCache[fetchKey].Count == 0;
+            }
+            if (completed) IncrementalSearchComplete(fetchKey);
+
+            int[] results = new int[sortedLists.Count];
+            float[] distances = new float[sortedLists.Count];
+            for (int i = 0; i < sortedLists.Count; i++)
+            {
+                results[i] = sortedLists[i].Item1;
+                distances[i] = sortedLists[i].Item2;
+            }
+            return (results.ToArray(), distances.ToArray(), completed);
+        }
+
+        public override void IncrementalSearchComplete(int fetchKey)
+        {
+            incrementalSearchCache.Remove(fetchKey);
+        }
+
+        protected override void ClearInternal()
+        {
+            embeddings.Clear();
+            incrementalSearchCache.Clear();
+        }
+
+        protected override void SaveInternal(ZipArchive archive)
+        {
+            ArchiveSaver.Save(archive, embeddings, GetSavePath("embeddings"));
+            ArchiveSaver.Save(archive, incrementalSearchCache, GetSavePath("incrementalSearchCache"));
+        }
+
+        protected override void LoadInternal(ZipArchive archive)
+        {
+            embeddings = ArchiveSaver.Load<SortedDictionary<int, float[]>>(archive, GetSavePath("embeddings"));
+            incrementalSearchCache = ArchiveSaver.Load<Dictionary<int, List<(int, float)>>>(archive, GetSavePath("incrementalSearchCache"));
+        }
+
+        /// \endcond
+    }
+}
diff --git a/Runtime/RAG/SimpleSearch.cs.meta b/Runtime/RAG/SimpleSearch.cs.meta
new file mode 100644
index 00000000..21d7f0ff
--- /dev/null
+++ b/Runtime/RAG/SimpleSearch.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5102d32385d84d87f98c64d376cbcc90
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/TokenSplitter.cs b/Runtime/RAG/TokenSplitter.cs
new file mode 100644
index 00000000..e95a9f0d
--- /dev/null
+++ b/Runtime/RAG/TokenSplitter.cs
@@ -0,0 +1,68 @@
+/// @file
+/// @brief File implementing a token-based splitter
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace LLMUnity
+{
+    /// @ingroup rag
+    /// <summary>
+    /// Class implementing a token-based splitter
+    /// </summary>
+    [Serializable]
+    public class TokenSplitter : Chunking
+    {
+        /// <summary> the number of tokens to split phrases into chunks </summary>
+        public int numTokens = 10;
+
+        protected int DetermineEndIndex(string input, string detokenised, int startIndex, int searchRange = 5, int charsFromEnd = 3)
+        {
+            int endIndex = Math.Min(input.Length - 1, startIndex + detokenised.Length - 1);
+            if (endIndex == input.Length - 1) return endIndex;
+
+            for (int lastCharI = 0; lastCharI < charsFromEnd; lastCharI++)
+            {
+                int charI = detokenised.Length - 1 - lastCharI;
+                if (charI < 0) break;
+                char lastChar = detokenised[charI];
+
+                for (int i = 0; i < searchRange; i++)
+                {
+                    foreach (int mul in new int[] {-1, 1})
+                    {
+                        int inputCharI = endIndex + mul * i;
+                        if (inputCharI < 0 || inputCharI > input.Length - 1) continue;
+                        if (input[inputCharI] == lastChar) return inputCharI;
+                    }
+                }
+            }
+            return endIndex;
+        }
+
+        /// <summary>
+        /// Splits the provided phrase into chunks of a specific number of tokens (defined by the numTokens variable)
+        /// </summary>
+        /// <param name="input">phrase</param>
+        /// <returns>List of start/end indices of the split chunks</returns>
+        public override async Task<List<(int, int)>> Split(string input)
+        {
+            List<(int, int)> indices = new List<(int, int)>();
+            List<int> tokens = await search.Tokenize(input);
+            if (tokens.Count == 0) return indices;
+
+            int startIndex = 0;
+            for (int i = 0; i < tokens.Count; i += numTokens)
+            {
+                int batchTokens = Math.Min(tokens.Count, i + numTokens) - i;
+                string detokenised = await search.Detokenize(tokens.GetRange(i, batchTokens));
+                int endIndex = DetermineEndIndex(input, detokenised, startIndex);
+                indices.Add((startIndex, endIndex));
+                startIndex = endIndex + 1;
+                if (endIndex == input.Length - 1) break;
+            }
+            if (startIndex <= input.Length - 1) indices.Add((startIndex, input.Length - 1));
+            return indices;
+        }
+    }
+}
diff --git a/Runtime/RAG/TokenSplitter.cs.meta b/Runtime/RAG/TokenSplitter.cs.meta
new file mode 100644
index 00000000..7e331a96
--- /dev/null
+++ b/Runtime/RAG/TokenSplitter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 783ce7a7cb52dc89eb18ad9d345ce68d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/WordSplitter.cs b/Runtime/RAG/WordSplitter.cs
new file mode 100644
index 00000000..f1540c61
--- /dev/null
+++ b/Runtime/RAG/WordSplitter.cs
@@ -0,0 +1,56 @@
+/// @file
+/// @brief File implementing a word-based splitter
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace LLMUnity
+{
+    /// @ingroup rag
+    /// <summary>
+    /// Class implementing a word-based splitter
+    /// </summary>
+    [Serializable]
+    public class WordSplitter : Chunking
+    {
+        /// <summary> the number of words to split phrases into chunks </summary>
+        public int numWords = 10;
+
+        /// <summary>
+        /// Splits the provided phrase into chunks of a specific number of words (defined by the numWords variable)
+        /// </summary>
+        /// <param name="input">phrase</param>
+        /// <returns>List of start/end indices of the split chunks</returns>
+        public override async Task<List<(int, int)>> Split(string input)
+        {
+            bool IsBoundary(char c)
+            {
+                return Char.IsPunctuation(c) || Char.IsWhiteSpace(c);
+            }
+
+            List<(int, int)> indices = new List<(int, int)>();
+            await Task.Run(() => {
+                List<(int, int)> wordIndices = new List<(int, int)>();
+                int startIndex = 0;
+                int endIndex;
+                for (int i = 0; i < input.Length; i++)
+                {
+                    if (i == input.Length - 1 || IsBoundary(input[i]))
+                    {
+                        while (i < input.Length - 1 && IsBoundary(input[i + 1])) i++;
+                        endIndex = i;
+                        wordIndices.Add((startIndex, endIndex));
+                        startIndex = i + 1;
+                    }
+                }
+
+                for (int i = 0; i < wordIndices.Count; i += numWords)
+                {
+                    int iTo = Math.Min(wordIndices.Count - 1, i + numWords - 1);
+                    indices.Add((wordIndices[i].Item1, wordIndices[iTo].Item2));
+                }
+            });
+            return indices;
+        }
+    }
+}
diff --git a/Runtime/RAG/WordSplitter.cs.meta b/Runtime/RAG/WordSplitter.cs.meta
new file mode 100644
index 00000000..b2d1be07
--- /dev/null
+++ b/Runtime/RAG/WordSplitter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 848a185d03c8d0bd4a047284c9a13bc6
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/usearch.meta b/Runtime/RAG/usearch.meta
new file mode 100644
index 00000000..019dfe6c
--- /dev/null
+++ b/Runtime/RAG/usearch.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 01a330e741823db8b987ccc961038a0c
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/usearch/Cloud.Unum.USearch.asmdef b/Runtime/RAG/usearch/Cloud.Unum.USearch.asmdef
new file mode 100644
index 00000000..adf4461e
--- /dev/null
+++ b/Runtime/RAG/usearch/Cloud.Unum.USearch.asmdef
@@ -0,0 +1,3 @@
+{
+	"name": "Cloud.Unum.USearch"
+}
diff --git a/Samples~/KnowledgeBaseGame/KnowledgeBase.asmdef.meta b/Runtime/RAG/usearch/Cloud.Unum.USearch.asmdef.meta
similarity index 76%
rename from Samples~/KnowledgeBaseGame/KnowledgeBase.asmdef.meta
rename to Runtime/RAG/usearch/Cloud.Unum.USearch.asmdef.meta
index 35a5d9b7..eebc7863 100644
--- a/Samples~/KnowledgeBaseGame/KnowledgeBase.asmdef.meta
+++ b/Runtime/RAG/usearch/Cloud.Unum.USearch.asmdef.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 42f2ee663135398278c988534b3ae0b3
+guid: 5cd85a883a79084e79040e24753a27a4
 AssemblyDefinitionImporter:
   externalObjects: {}
   userData: 
diff --git a/Runtime/RAG/usearch/LICENSE b/Runtime/RAG/usearch/LICENSE
new file mode 100644
index 00000000..261eeb9e
--- /dev/null
+++ b/Runtime/RAG/usearch/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/Runtime/RAG/usearch/LICENSE.meta b/Runtime/RAG/usearch/LICENSE.meta
new file mode 100644
index 00000000..eea86eee
--- /dev/null
+++ b/Runtime/RAG/usearch/LICENSE.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 974cd1ee69b60ce01a6746e41ac03d19
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/usearch/NativeMethods.cs b/Runtime/RAG/usearch/NativeMethods.cs
new file mode 100644
index 00000000..34ba5898
--- /dev/null
+++ b/Runtime/RAG/usearch/NativeMethods.cs
@@ -0,0 +1,155 @@
+using System.Runtime.InteropServices;
+
+using usearch_index_t = System.IntPtr;
+using usearch_key_t = System.UInt64;
+using usearch_error_t = System.IntPtr;
+using size_t = System.UIntPtr;
+using void_ptr_t = System.IntPtr;
+using usearch_distance_t = System.Single;
+
+namespace Cloud.Unum.USearch
+{
+    public static class NativeMethods
+    {
+        private const string LibraryName = "libusearch_c";
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern usearch_index_t usearch_init(ref IndexOptions options, out usearch_error_t error);
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern void usearch_free(usearch_index_t index, out usearch_error_t error);
+
+        [DllImport(LibraryName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
+        public static extern void usearch_save(usearch_index_t index, [MarshalAs(UnmanagedType.LPStr)] string path, out usearch_error_t error);
+
+        [DllImport(LibraryName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
+        public static extern void usearch_load(usearch_index_t index, [MarshalAs(UnmanagedType.LPStr)] string path, out usearch_error_t error);
+
+        [DllImport(LibraryName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
+        public static extern void usearch_view(usearch_index_t index, [MarshalAs(UnmanagedType.LPStr)] string path, out usearch_error_t error);
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_size(usearch_index_t index, out usearch_error_t error);
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_capacity(usearch_index_t index, out usearch_error_t error);
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_dimensions(usearch_index_t index, out usearch_error_t error);
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_connectivity(usearch_index_t index, out usearch_error_t error);
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern void usearch_reserve(usearch_index_t index, size_t capacity, out usearch_error_t error);
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern void usearch_add(
+            usearch_index_t index,
+            usearch_key_t key,
+            [In] float[] vector,
+            ScalarKind vector_kind,
+            out usearch_error_t error
+        );
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern void usearch_add(
+            usearch_index_t index,
+            usearch_key_t key,
+            [In] double[] vector,
+            ScalarKind vector_kind,
+            out usearch_error_t error
+        );
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        [return : MarshalAs(UnmanagedType.I1)]
+        public static extern bool usearch_contains(usearch_index_t index, usearch_key_t key, out usearch_error_t error);
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_count(usearch_index_t index, usearch_key_t key, out usearch_error_t error);
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_search(
+            usearch_index_t index,
+            void_ptr_t query_vector,
+            ScalarKind query_kind,
+            size_t count,
+            [Out] usearch_key_t[] found_keys,
+            [Out] usearch_distance_t[] found_distances,
+            out usearch_error_t error
+        );
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_search(
+            usearch_index_t index,
+            [In] float[] query_vector,
+            ScalarKind query_kind,
+            size_t count,
+            [Out] usearch_key_t[] found_keys,
+            [Out] usearch_distance_t[] found_distances,
+            out usearch_error_t error
+        );
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_search(
+            usearch_index_t index,
+            [In] double[] query_vector,
+            ScalarKind query_kind,
+            size_t count,
+            [Out] usearch_key_t[] found_keys,
+            [Out] usearch_distance_t[] found_distances,
+            out usearch_error_t error
+        );
+
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_get(
+            usearch_index_t index,
+            usearch_key_t key,
+            size_t count,
+            [Out] float[] vector,
+            ScalarKind vector_kind,
+            out usearch_error_t error
+        );
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_get(
+            usearch_index_t index,
+            usearch_key_t key,
+            size_t count,
+            [Out] double[] vector,
+            ScalarKind vector_kind,
+            out usearch_error_t error
+        );
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_remove(usearch_index_t index, usearch_key_t key, out usearch_error_t error);
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_rename(usearch_index_t index, usearch_key_t key_from, usearch_key_t key_to, out usearch_error_t error);
+
+        //========================== Additional methods from LLMUnity ==========================//
+
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        public delegate int FilterCallback(int key, void_ptr_t filterState);
+
+        [DllImport(LibraryName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
+        public static extern void usearch_load_buffer(usearch_index_t index, void_ptr_t buffer, size_t length, out usearch_error_t error);
+
+        [DllImport(LibraryName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
+        public static extern void usearch_view_buffer(usearch_index_t index, void_ptr_t buffer, size_t length, out usearch_error_t error);
+
+        [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
+        public static extern size_t usearch_filtered_search(
+            usearch_index_t index,
+            void_ptr_t query_vector,
+            ScalarKind query_kind,
+            size_t count,
+            FilterCallback filter,
+            void_ptr_t filterState,
+            [Out] usearch_key_t[] found_keys,
+            [Out] usearch_distance_t[] found_distances,
+            out usearch_error_t error
+        );
+    }
+}
diff --git a/Runtime/RAG/usearch/NativeMethods.cs.meta b/Runtime/RAG/usearch/NativeMethods.cs.meta
new file mode 100644
index 00000000..ba483ac8
--- /dev/null
+++ b/Runtime/RAG/usearch/NativeMethods.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: eec2de19e997c7c9e81c4c1f3dd6b78f
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/usearch/README.md b/Runtime/RAG/usearch/README.md
new file mode 100644
index 00000000..ea420ed2
--- /dev/null
+++ b/Runtime/RAG/usearch/README.md
@@ -0,0 +1,468 @@
+# USearch
+## Description
+USearch is a Similarity Search Engine.
+The USearch repository can be found here: https://github.com/unum-cloud/usearch/
+
+## License
+USearch is distributed under Apache-2.0 license, see the [LICENSE file](LICENSE).
+
+## Local Modifications
+The files from the C# code here: https://github.com/unum-cloud/usearch/tree/main/csharp/src/Cloud.Unum.USearch
+have been copied inside this folder.
+
+Additionally, the runtime dlls have been exported from the nuget package downloaded from here:
+https://www.nuget.org/packages/Cloud.Unum.USearch
+and added in the x86_64 folder.
+
+The following modifications have been applied
+- NativeMethods.cs: the usearch_view_buffer and usearch_load_buffer are being imported
+- USearchIndex.cs: the save and load functions have been modified to save/load the IndexOptions along with the index in a ZipArchive
+- .meta files have been automatically added by Unity
+- a Cloud.Unum.USearch.asmdef file has been added to denote the name of the package
+- the dll file inside the arm64 has been compiled for arm64 macOS from the USearch code repository.
+
+## Original Readme
+The original readme is appended here:
+
+-----
+
+<h1 align="center">USearch</h1>
+<h3 align="center">
+Smaller & <a href="https://www.unum.cloud/blog/2023-11-07-scaling-vector-search-with-intel">Faster</a> Single-File<br/>
+Similarity Search Engine for <a href="https://github.com/ashvardanian/simsimd">Vectors</a> & 🔜 <a href="https://github.com/ashvardanian/stringzilla">Texts</a>
+</h3>
+<br/>
+
+<p align="center">
+<a href="https://discord.gg/A6wxt6dS9j"><img height="25" src="https://github.com/unum-cloud/.github/raw/main/assets/discord.svg" alt="Discord"></a>
+&nbsp;&nbsp;&nbsp;
+<a href="https://www.linkedin.com/company/unum-cloud/"><img height="25" src="https://github.com/unum-cloud/.github/raw/main/assets/linkedin.svg" alt="LinkedIn"></a>
+&nbsp;&nbsp;&nbsp;
+<a href="https://twitter.com/unum_cloud"><img height="25" src="https://github.com/unum-cloud/.github/raw/main/assets/twitter.svg" alt="Twitter"></a>
+&nbsp;&nbsp;&nbsp;
+<a href="https://unum.cloud/post"><img height="25" src="https://github.com/unum-cloud/.github/raw/main/assets/blog.svg" alt="Blog"></a>
+&nbsp;&nbsp;&nbsp;
+<a href="https://github.com/unum-cloud/usearch"><img height="25" src="https://github.com/unum-cloud/.github/raw/main/assets/github.svg" alt="GitHub"></a>
+</p>
+
+<p align="center">
+Spatial • Binary • Probabilistic • User-Defined Metrics
+<br/>
+<a href="https://unum-cloud.github.io/usearch/cpp">C++ 11</a> •
+<a href="https://unum-cloud.github.io/usearch/python">Python 3</a> •
+<a href="https://unum-cloud.github.io/usearch/javascript">JavaScript</a> •
+<a href="https://unum-cloud.github.io/usearch/java">Java</a> •
+<a href="https://unum-cloud.github.io/usearch/rust">Rust</a> •
+<a href="https://unum-cloud.github.io/usearch/c">C 99</a> •
+<a href="https://unum-cloud.github.io/usearch/objective-c">Objective-C</a> •
+<a href="https://unum-cloud.github.io/usearch/swift">Swift</a> •
+<a href="https://unum-cloud.github.io/usearch/csharp">C#</a> •
+<a href="https://unum-cloud.github.io/usearch/golang">GoLang</a> •
+<a href="https://unum-cloud.github.io/usearch/wolfram">Wolfram</a>
+<br/>
+Linux • MacOS • Windows • iOS • WebAssembly
+</p>
+
+<div align="center">
+<a href="https://pepy.tech/project/usearch"> <img alt="PyPI" src="https://static.pepy.tech/personalized-badge/usearch?period=total&units=abbreviation&left_color=black&right_color=blue&left_text=USearch%20Python%20installs"> </a>
+<a href="https://www.npmjs.com/package/usearch"> <img alt="NPM" src="https://img.shields.io/npm/dy/usearch?label=NPM%20installs"> </a>
+<a href="https://crates.io/crates/usearch"> <img alt="Crate" src="https://img.shields.io/crates/d/usearch?label=Crate%20installs"> </a>
+<a href="https://www.nuget.org/packages/Cloud.Unum.USearch"> <img alt="NuGet" src="https://img.shields.io/nuget/dt/Cloud.Unum.USearch?label=NuGet%20installs"> </a>
+<a href="https://central.sonatype.com/artifact/cloud.unum/usearch/overview"> <img alt="Maven" src="https://img.shields.io/nexus/r/cloud.unum/usearch?server=https%3A%2F%2Fs01.oss.sonatype.org%2F&label=Maven%20version"> </a>
+<a href="https://hub.docker.com/r/unum/usearch"> <img alt="Docker" src="https://img.shields.io/docker/pulls/unum/usearch?label=Docker%20installs"> </a>
+<img alt="GitHub code size in bytes" src="https://img.shields.io/github/languages/code-size/unum-cloud/usearch?label=Repo%20size">
+</div>
+
+---
+
+- ✅ [10x faster][faster-than-faiss] [HNSW][hnsw-algorithm] implementation than [FAISS][faiss].
+- ✅ Simple and extensible [single C++11 header][usearch-header] implementation.
+- ✅ Compatible with a dozen programming languages out of the box.
+- ✅ [Trusted](#integrations) by some of the most loved Datalakes and Databases, like [ClickHouse][clickhouse-docs].
+- ✅ [SIMD][simd]-optimized and [user-defined metrics](#user-defined-functions) with JIT compilation.
+- ✅ Hardware-agnostic `f16` & `i8` - [half-precision & quarter-precision support](#memory-efficiency-downcasting-and-quantization).
+- ✅ [View large indexes from disk](#serving-index-from-disk) without loading into RAM.
+- ✅ Heterogeneous lookups, renaming/relabeling, and on-the-fly deletions.
+- ✅ Variable dimensionality vectors for unique applications, including search over compressed data.
+- ✅ Binary Tanimoto and Sorensen coefficients for [Genomics and Chemistry applications](#usearch--rdkit--molecular-search).
+- ✅ Space-efficient point-clouds with `uint40_t`, accommodating 4B+ size.
+- ✅ Compatible with OpenMP and custom "executors" for fine-grained control over CPU utilization.
+- ✅ Near-real-time [clustering and sub-clustering](#clustering) for Tens or Millions of clusters.
+- ✅ [Semantic Search](#usearch--ai--multi-modal-semantic-search) and [Joins](#joins).
+
+[faiss]: https://github.com/facebookresearch/faiss
+[usearch-header]: https://github.com/unum-cloud/usearch/blob/main/include/usearch/index.hpp
+[obscure-use-cases]: https://ashvardanian.com/posts/abusing-vector-search
+[hnsw-algorithm]: https://arxiv.org/abs/1603.09320
+[simd]: https://en.wikipedia.org/wiki/Single_instruction,_multiple_data
+[faster-than-faiss]: https://www.unum.cloud/blog/2023-11-07-scaling-vector-search-with-intel
+[clickhouse-docs]: https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/annindexes#usearch
+
+__Technical Insights__ and related articles:
+
+- [Uses Horner's method for polynomial approximations, beating GCC 12 by 119x](https://ashvardanian.com/posts/gcc-12-vs-avx512fp16/).
+- [Uses Arm SVE and x86 AVX-512's masked loads to eliminate tail `for`-loops](https://ashvardanian.com/posts/simsimd-faster-scipy/#tails-of-the-past-the-significance-of-masked-loads).
+- [Uses AVX-512 FP16 for half-precision operations, that few compilers vectorize](https://ashvardanian.com/posts/simsimd-faster-scipy/#the-challenge-of-f16).
+- [Substitutes LibC's `sqrt` calls with bithacks using Jan Kadlec's constant](https://ashvardanian.com/posts/simsimd-faster-scipy/#bonus-section-bypassing-sqrt-and-libc-dependencies).
+- [For every language implements a custom separate binding](https://ashvardanian.com/posts/porting-cpp-library-to-ten-languages/).
+- [For Python avoids slow PyBind11, and even `PyArg_ParseTuple` for speed](https://ashvardanian.com/posts/pybind11-cpython-tutorial/).
+- [For JavaScript uses typed arrays and NAPI for zero-copy calls](https://ashvardanian.com/posts/javascript-ai-vector-search/).
+
+## Comparison with FAISS
+
+FAISS is a widely recognized standard for high-performance vector search engines.
+USearch and FAISS both employ the same HNSW algorithm, but they differ significantly in their design principles.
+USearch is compact and broadly compatible without sacrificing performance, primarily focusing on user-defined metrics and fewer dependencies.
+
+|                                              |                   FAISS |                  USearch |             Improvement |
+| :------------------------------------------- | ----------------------: | -----------------------: | ----------------------: |
+| Indexing time ⁰                              |                         |                          |                         |
+| 100 Million 96d `f32`, `f16`, `i8` vectors   |       2.6 · 2.6 · 2.6 h |        0.3 · 0.2 · 0.2 h | __9.6 · 10.4 · 10.7 x__ |
+| 100 Million 1536d `f32`, `f16`, `i8` vectors |       5.0 · 4.1 · 3.8 h |        2.1 · 1.1 · 0.8 h |   __2.3 · 3.6 · 4.4 x__ |
+|                                              |                         |                          |                         |
+| Codebase length ¹                            |       84 K [SLOC][sloc] |         3 K [SLOC][sloc] |            maintainable |
+| Supported metrics ²                          |         9 fixed metrics |               any metric |              extendible |
+| Supported languages ³                        |             C++, Python |             10 languages |                portable |
+| Supported ID types ⁴                         |          32-bit, 64-bit |   32-bit, 40-bit, 64-bit |               efficient |
+| Required dependencies ⁵                      |            BLAS, OpenMP |                        - |            light-weight |
+| Bindings ⁶                                   |                    SWIG |                   Native |             low-latency |
+| Python binding size ⁷                        | [~ 10 MB][faiss-weight] | [< 1 MB][usearch-weight] |              deployable |
+
+[sloc]: https://en.wikipedia.org/wiki/Source_lines_of_code
+[faiss-weight]: https://pypi.org/project/faiss-cpu/#files
+[usearch-weight]: https://pypi.org/project/usearch/#files
+
+> ⁰ [Tested][intel-benchmarks] on Intel Sapphire Rapids, with the simplest inner-product distance, equivalent recall, and memory consumption while also providing far superior search speed.
+> ¹ A shorter codebase of `usearch/` over `faiss/` makes the project easier to maintain and audit.
+> ² User-defined metrics allow you to customize your search for various applications, from GIS to creating custom metrics for composite embeddings from multiple AI models or hybrid full-text and semantic search.
+> ³ With USearch, you can reuse the same preconstructed index in various programming languages.
+> ⁴ The 40-bit integer allows you to store 4B+ vectors without allocating 8 bytes for every neighbor reference in the proximity graph.
+> ⁵ Lack of obligatory dependencies makes USearch much more portable.
+> ⁶ Native bindings introduce lower call latencies than more straightforward approaches.
+> ⁷ Lighter bindings make downloads and deployments faster.
+
+[intel-benchmarks]: https://www.unum.cloud/blog/2023-11-07-scaling-vector-search-with-intel
+
+Base functionality is identical to FAISS, and the interface must be familiar if you have ever investigated Approximate Nearest Neighbors search:
+
+```py
+$ pip install numpy usearch
+
+import numpy as np
+from usearch.index import Index
+
+index = Index(ndim=3)
+
+vector = np.array([0.2, 0.6, 0.4])
+index.add(42, vector)
+
+matches = index.search(vector, 10)
+
+assert matches[0].key == 42
+assert matches[0].distance <= 0.001
+assert np.allclose(index[42], vector)
+```
+
+More settings are always available, and the API is designed to be as flexible as possible.
+
+```py
+index = Index(
+    ndim=3, # Define the number of dimensions in input vectors
+    metric='cos', # Choose 'l2sq', 'haversine' or other metric, default = 'ip'
+    dtype='f32', # Quantize to 'f16' or 'i8' if needed, default = 'f32'
+    connectivity=16, # Optional: Limit number of neighbors per graph node
+    expansion_add=128, # Optional: Control the recall of indexing
+    expansion_search=64, # Optional: Control the quality of the search
+    multi=False, # Optional: Allow multiple vectors per key, default = False
+)
+```
+
+## Serialization & Serving `Index` from Disk
+
+USearch supports multiple forms of serialization:
+
+- Into a __file__ defined with a path.
+- Into a __stream__ defined with a callback, serializing or reconstructing incrementally.
+- Into a __buffer__ of fixed length or a memory-mapped file that supports random access.
+
+The latter allows you to serve indexes from external memory, enabling you to optimize your server choices for indexing speed and serving costs.
+This can result in __20x cost reduction__ on AWS and other public clouds.
+
+```py
+index.save("index.usearch")
+
+loaded_copy = index.load("index.usearch")
+view = Index.restore("index.usearch", view=True)
+
+other_view = Index(ndim=..., metric=...)
+other_view.view("index.usearch")
+```
+
+## Exact vs. Approximate Search
+
+Approximate search methods, such as HNSW, are predominantly used when an exact brute-force search becomes too resource-intensive.
+This typically occurs when you have millions of entries in a collection.
+For smaller collections, we offer a more direct approach with the `search` method.
+
+```py
+from usearch.index import search, MetricKind, Matches, BatchMatches
+import numpy as np
+
+# Generate 10'000 random vectors with 1024 dimensions
+vectors = np.random.rand(10_000, 1024).astype(np.float32)
+vector = np.random.rand(1024).astype(np.float32)
+
+one_in_many: Matches = search(vectors, vector, 50, MetricKind.L2sq, exact=True)
+many_in_many: BatchMatches = search(vectors, vectors, 50, MetricKind.L2sq, exact=True)
+```
+
+If you pass the `exact=True` argument, the system bypasses indexing altogether and performs a brute-force search through the entire dataset using SIMD-optimized similarity metrics from [SimSIMD](https://github.com/ashvardanian/simsimd).
+When compared to FAISS's `IndexFlatL2` in Google Colab, __[USearch may offer up to a 20x performance improvement](https://github.com/unum-cloud/usearch/issues/176#issuecomment-1666650778)__:
+
+- `faiss.IndexFlatL2`: __55.3 ms__.
+- `usearch.index.search`: __2.54 ms__.
+
+## `Indexes` for Multi-Index Lookups
+
+For larger workloads targeting billions or even trillions of vectors, parallel multi-index lookups become invaluable.
+Instead of constructing one extensive index, you can build multiple smaller ones and view them together.
+
+```py
+from usearch.index import Indexes
+
+multi_index = Indexes(
+    indexes: Iterable[usearch.index.Index] = [...],
+    paths: Iterable[os.PathLike] = [...],
+    view: bool = False,
+    threads: int = 0,
+)
+multi_index.search(...)
+```
+
+## Clustering
+
+Once the index is constructed, USearch can perform K-Nearest Neighbors Clustering much faster than standalone clustering libraries, like SciPy, 
+UMap, and tSNE.
+Same for dimensionality reduction with PCA. 
+Essentially, the `Index` itself can be seen as a clustering, allowing iterative deepening.
+
+```py
+clustering = index.cluster(
+    min_count=10, # Optional
+    max_count=15, # Optional
+    threads=..., # Optional
+)
+
+# Get the clusters and their sizes
+centroid_keys, sizes = clustering.centroids_popularity
+
+# Use Matplotlib to draw a histogram
+clustering.plot_centroids_popularity()
+
+# Export a NetworkX graph of the clusters
+g = clustering.network
+
+# Get members of a specific cluster
+first_members = clustering.members_of(centroid_keys[0])
+
+# Deepen into that cluster, splitting it into more parts, all the same arguments supported
+sub_clustering = clustering.subcluster(min_count=..., max_count=...)
+```
+
+The resulting clustering isn't identical to K-Means or other conventional approaches but serves the same purpose.
+Alternatively, using Scikit-Learn on a 1 Million point dataset, one may expect queries to take anywhere from minutes to hours, depending on the number of clusters you want to highlight.
+For 50'000 clusters, the performance difference between USearch and conventional clustering methods may easily reach 100x.
+
+## Joins, One-to-One, One-to-Many, and Many-to-Many Mappings
+
+One of the big questions these days is how AI will change the world of databases and data management.
+Most databases are still struggling to implement high-quality fuzzy search, and the only kind of joins they know are deterministic.
+A `join` differs from searching for every entry, requiring a one-to-one mapping banning collisions among separate search results.
+
+| Exact Search | Fuzzy Search | Semantic Search ? |
+| :----------: | :----------: | :---------------: |
+|  Exact Join  | Fuzzy Join ? | Semantic Join ??  |
+
+Using USearch, one can implement sub-quadratic complexity approximate, fuzzy, and semantic joins.
+This can be useful in any fuzzy-matching tasks common to Database Management Software.
+
+```py
+men = Index(...)
+women = Index(...)
+pairs: dict = men.join(women, max_proposals=0, exact=False)
+```
+
+> Read more in the post: [Combinatorial Stable Marriages for Semantic Search 💍](https://ashvardanian.com/posts/searching-stable-marriages)
+
+## User-Defined Functions
+
+While most vector search packages concentrate on just a few metrics - "Inner Product distance" and "Euclidean distance," USearch extends this list to include any user-defined metrics.
+This flexibility allows you to customize your search for various applications, from computing geospatial coordinates with the rare [Haversine][haversine] distance to creating custom metrics for composite embeddings from multiple AI models.
+
+![USearch: Vector Search Approaches](https://github.com/unum-cloud/usearch/blob/main/assets/usearch-approaches-white.png?raw=true)
+
+Unlike older approaches indexing high-dimensional spaces, like KD-Trees and Locality Sensitive Hashing, HNSW doesn't require vectors to be identical in length.
+They only have to be comparable.
+So you can apply it in [obscure][obscure] applications, like searching for similar sets or fuzzy text matching, using [GZip][gzip-similarity] as a distance function.
+
+> Read more about [JIT and UDF in USearch Python SDK](https://unum-cloud.github.io/usearch/python#user-defined-metrics-and-jit-in-python).
+
+[haversine]: https://ashvardanian.com/posts/abusing-vector-search#geo-spatial-indexing
+[obscure]: https://ashvardanian.com/posts/abusing-vector-search
+[gzip-similarity]: https://twitter.com/LukeGessler/status/1679211291292889100?s=20
+
+## Memory Efficiency, Downcasting, and Quantization
+
+Training a quantization model and dimension-reduction is a common approach to accelerate vector search.
+Those, however, are only sometimes reliable, can significantly affect the statistical properties of your data, and require regular adjustments if your distribution shifts.
+Instead, we have focused on high-precision arithmetic over low-precision downcasted vectors.
+The same index, and `add` and `search` operations will automatically down-cast or up-cast between `f64_t`, `f32_t`, `f16_t`, `i8_t`, and single-bit representations.
+You can use the following command to check, if hardware acceleration is enabled:
+
+```sh
+$ python -c 'from usearch.index import Index; print(Index(ndim=768, metric="cos", dtype="f16").hardware_acceleration)'
+> avx512+f16
+$ python -c 'from usearch.index import Index; print(Index(ndim=166, metric="tanimoto").hardware_acceleration)'
+> avx512+popcnt
+```
+
+Using smaller numeric types will save you RAM needed to store the vectors, but you can also compress the neighbors lists forming our proximity graphs.
+By default, 32-bit `uint32_t` is used to enumerate those, which is not enough if you need to address over 4 Billion entries.
+For such cases we provide a custom `uint40_t` type, that will still be 37.5% more space-efficient than the commonly used 8-byte integers, and will scale up to 1 Trillion entries.
+
+![USearch uint40_t support](https://github.com/unum-cloud/usearch/blob/main/assets/usearch-neighbor-types.png?raw=true)
+
+## Functionality
+
+By now, the core functionality is supported across all bindings.
+Broader functionality is ported per request.
+In some cases, like Batch operations, feature parity is meaningless, as the host language has full multi-threading capabilities and the USearch index structure is concurrent by design, so the users can implement batching/scheduling/load-balancing in the most optimal way for their applications.
+
+|                         | C++ 11 | Python 3 | C 99  | Java  | JavaScript | Rust  | GoLang | Swift |
+| :---------------------- | :----: | :------: | :---: | :---: | :--------: | :---: | :----: | :---: |
+| Add, search, remove     |   ✅    |    ✅     |   ✅   |   ✅   |     ✅      |   ✅   |   ✅    |   ✅   |
+| Save, load, view        |   ✅    |    ✅     |   ✅   |   ✅   |     ✅      |   ✅   |   ✅    |   ✅   |
+| User-defined metrics    |   ✅    |    ✅     |   ✅   |   ❌   |     ❌      |   ❌   |   ❌    |   ❌   |
+| Batch operations        |   ❌    |    ✅     |   ❌   |   ❌   |     ✅      |   ❌   |   ❌    |   ❌   |
+| Joins                   |   ✅    |    ✅     |   ❌   |   ❌   |     ❌      |   ❌   |   ❌    |   ❌   |
+| Variable-length vectors |   ✅    |    ❌     |   ❌   |   ❌   |     ❌      |   ❌   |   ❌    |   ❌   |
+| 4B+ capacities          |   ✅    |    ❌     |   ❌   |   ❌   |     ❌      |   ❌   |   ❌    |   ❌   |
+
+## Application Examples
+
+### USearch + AI = Multi-Modal Semantic Search
+
+[![USearch Semantic Image Search](https://github.com/ashvardanian/usearch-images/raw/main/assets/usearch-images-slow.gif)](https://github.com/ashvardanian/usearch-images)
+
+AI has a growing number of applications, but one of the coolest classic ideas is to use it for Semantic Search.
+One can take an encoder model, like the multi-modal [UForm](https://github.com/unum-cloud/uform), and a web-programming framework, like UCall, and build a text-to-image search platform in just 20 lines of Python.
+
+```python
+import ucall
+import uform
+import usearch
+
+import numpy as np
+import PIL as pil
+
+server = ucall.Server()
+model = uform.get_model('unum-cloud/uform-vl-multilingual')
+index = usearch.index.Index(ndim=256)
+
+@server
+def add(key: int, photo: pil.Image.Image):
+    image = model.preprocess_image(photo)
+    vector = model.encode_image(image).detach().numpy()
+    index.add(key, vector.flatten(), copy=True)
+
+@server
+def search(query: str) -> np.ndarray:
+    tokens = model.preprocess_text(query)
+    vector = model.encode_text(tokens).detach().numpy()
+    matches = index.search(vector.flatten(), 3)
+    return matches.keys
+
+server.run()
+```
+
+A more complete [demo with Streamlit is available on GitHub](https://github.com/ashvardanian/usearch-images).
+We have pre-processed some commonly used datasets, cleaned the images, produced the vectors, and pre-built the index.
+
+| Dataset                             |            Modalities | Images |                              Download |
+| :---------------------------------- | --------------------: | -----: | ------------------------------------: |
+| [Unsplash][unsplash-25k-origin]     | Images & Descriptions |   25 K | [HuggingFace / Unum][unsplash-25k-hf] |
+| [Conceptual Captions][cc-3m-origin] | Images & Descriptions |    3 M |        [HuggingFace / Unum][cc-3m-hf] |
+| [Arxiv][arxiv-2m-origin]            |    Titles & Abstracts |    2 M |     [HuggingFace / Unum][arxiv-2m-hf] |
+
+[unsplash-25k-origin]: https://github.com/unsplash/datasets
+[cc-3m-origin]: https://huggingface.co/datasets/conceptual_captions
+[arxiv-2m-origin]: https://www.kaggle.com/datasets/Cornell-University/arxiv
+
+[unsplash-25k-hf]: https://huggingface.co/datasets/unum-cloud/ann-unsplash-25k
+[cc-3m-hf]: https://huggingface.co/datasets/unum-cloud/ann-cc-3m
+[arxiv-2m-hf]: https://huggingface.co/datasets/unum-cloud/ann-arxiv-2m
+
+### USearch + RDKit = Molecular Search
+
+Comparing molecule graphs and searching for similar structures is expensive and slow.
+It can be seen as a special case of the NP-Complete Subgraph Isomorphism problem.
+Luckily, domain-specific approximate methods exist.
+The one commonly used in Chemistry is to generate structures from [SMILES][smiles] and later hash them into binary fingerprints.
+The latter are searchable with binary similarity metrics, like the Tanimoto coefficient.
+Below is an example using the RDKit package.
+
+```python
+from usearch.index import Index, MetricKind
+from rdkit import Chem
+from rdkit.Chem import AllChem
+
+import numpy as np
+
+molecules = [Chem.MolFromSmiles('CCOC'), Chem.MolFromSmiles('CCO')]
+encoder = AllChem.GetRDKitFPGenerator()
+
+fingerprints = np.vstack([encoder.GetFingerprint(x) for x in molecules])
+fingerprints = np.packbits(fingerprints, axis=1)
+
+index = Index(ndim=2048, metric=MetricKind.Tanimoto)
+keys = np.arange(len(molecules))
+
+index.add(keys, fingerprints)
+matches = index.search(fingerprints, 10)
+```
+
+That method was used to build the ["USearch Molecules"](https://github.com/ashvardanian/usearch-molecules), one of the largest Chem-Informatics datasets, containing 7 billion small molecules and 28 billion fingerprints.
+
+[smiles]: https://en.wikipedia.org/wiki/Simplified_molecular-input_line-entry_system
+[rdkit-fingerprints]: https://www.rdkit.org/docs/RDKit_Book.html#additional-information-about-the-fingerprints
+
+### USearch + POI Coordinates = GIS Applications... on iOS?
+
+[![USearch Maps with SwiftUI](https://github.com/ashvardanian/SwiftVectorSearch/raw/main/USearch+SwiftUI.gif)](https://github.com/ashvardanian/SwiftVectorSearch)
+
+With Objective-C and Swift iOS bindings, USearch can be easily used in mobile applications.
+The [SwiftVectorSearch](https://github.com/ashvardanian/SwiftVectorSearch) project illustrates how to build a dynamic, real-time search system on iOS.
+In this example, we use 2-dimensional vectors—encoded as latitude and longitude—to find the closest Points of Interest (POIs) on a map.
+The search is based on the Haversine distance metric but can easily be extended to support high-dimensional vectors.
+
+## Integrations
+
+- [x] GPTCache: [Python](https://github.com/zilliztech/GPTCache/releases/tag/0.1.29).
+- [x] LangChain: [Python](https://github.com/langchain-ai/langchain/releases/tag/v0.0.257) and [JavaScript](https://github.com/hwchase17/langchainjs/releases/tag/0.0.125).
+- [x] ClickHouse: [C++](https://github.com/ClickHouse/ClickHouse/pull/53447).
+- [x] Microsoft Semantic Kernel: [Python](https://github.com/microsoft/semantic-kernel/releases/tag/python-0.3.9.dev) and C#.
+- [x] LanternDB: [C++](https://github.com/lanterndata/lantern) and [Rust](https://github.com/lanterndata/lantern_extras).
+
+## Citations
+
+```txt
+@software{Vardanian_USearch_2023,
+doi = {10.5281/zenodo.7949416},
+author = {Vardanian, Ash},
+title = {{USearch by Unum Cloud}},
+url = {https://github.com/unum-cloud/usearch},
+version = {2.8.16},
+year = {2023},
+month = oct,
+}
+```
diff --git a/Runtime/RAG/usearch/README.md.meta b/Runtime/RAG/usearch/README.md.meta
new file mode 100644
index 00000000..fa1c62fe
--- /dev/null
+++ b/Runtime/RAG/usearch/README.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: e64a900087d96cf7fbdefd8a24819eb8
+TextScriptImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/usearch/USearchException.cs b/Runtime/RAG/usearch/USearchException.cs
new file mode 100644
index 00000000..5f5f258d
--- /dev/null
+++ b/Runtime/RAG/usearch/USearchException.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Cloud.Unum.USearch
+{
+    public class USearchException : Exception
+    {
+        public USearchException(string message) : base(message) {}
+    }
+}
diff --git a/Runtime/RAG/usearch/USearchException.cs.meta b/Runtime/RAG/usearch/USearchException.cs.meta
new file mode 100644
index 00000000..f3ff8a54
--- /dev/null
+++ b/Runtime/RAG/usearch/USearchException.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 587fe86c17f98ed86af2b0adda713e91
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/usearch/USearchIndex.cs b/Runtime/RAG/usearch/USearchIndex.cs
new file mode 100644
index 00000000..9c9b39c4
--- /dev/null
+++ b/Runtime/RAG/usearch/USearchIndex.cs
@@ -0,0 +1,419 @@
+using System;
+using System.IO;
+using System.IO.Compression;
+using System.Runtime.InteropServices;
+using AOT;
+using UnityEngine;
+using static Cloud.Unum.USearch.NativeMethods;
+
+namespace Cloud.Unum.USearch
+{
+    /// <summary>
+    /// USearchIndex class provides a managed wrapper for the USearch library's index functionality.
+    /// </summary>
+    public class USearchIndex : IDisposable
+    {
+        private IntPtr _index;
+        private bool _disposedValue = false;
+        private ulong _cachedDimensions;
+
+        public USearchIndex(
+            MetricKind metricKind,
+            ScalarKind quantization,
+            ulong dimensions,
+            ulong connectivity = 0,
+            ulong expansionAdd = 0,
+            ulong expansionSearch = 0,
+            bool multi = false
+                //CustomDistanceFunction? customMetric = null
+        )
+        {
+            IndexOptions initOptions = new()
+            {
+                metric_kind = metricKind,
+                metric = default,
+                quantization = quantization,
+                dimensions = dimensions,
+                connectivity = connectivity,
+                expansion_add = expansionAdd,
+                expansion_search = expansionSearch,
+                multi = multi
+            };
+
+            this._index = usearch_init(ref initOptions, out IntPtr error);
+            HandleError(error);
+            this._cachedDimensions = dimensions;
+        }
+
+        public USearchIndex(IndexOptions options)
+        {
+            this._index = usearch_init(ref options, out IntPtr error);
+            HandleError(error);
+            this._cachedDimensions = options.dimensions;
+        }
+
+        public USearchIndex(string path, bool view = false)
+        {
+            IndexOptions initOptions = new();
+            this._index = usearch_init(ref initOptions, out IntPtr error);
+            HandleError(error);
+
+            if (view)
+            {
+                usearch_view(this._index, path, out error);
+            }
+            else
+            {
+                usearch_load(this._index, path, out error);
+            }
+
+            HandleError(error);
+
+            this._cachedDimensions = this.Dimensions();
+        }
+
+        public void Save(string path)
+        {
+            usearch_save(this._index, path, out IntPtr error);
+            HandleError(error);
+        }
+
+        public ulong Size()
+        {
+            ulong size = (ulong)usearch_size(this._index, out IntPtr error);
+            HandleError(error);
+            return size;
+        }
+
+        public ulong Capacity()
+        {
+            ulong capacity = (ulong)usearch_capacity(this._index, out IntPtr error);
+            HandleError(error);
+            return capacity;
+        }
+
+        public ulong Dimensions()
+        {
+            ulong dimensions = (ulong)usearch_dimensions(this._index, out IntPtr error);
+            HandleError(error);
+            return dimensions;
+        }
+
+        public ulong Connectivity()
+        {
+            ulong connectivity = (ulong)usearch_connectivity(this._index, out IntPtr error);
+            HandleError(error);
+            return connectivity;
+        }
+
+        public bool Contains(ulong key)
+        {
+            bool result = usearch_contains(this._index, key, out IntPtr error);
+            HandleError(error);
+            return result;
+        }
+
+        public int Count(ulong key)
+        {
+            int count = checked((int)usearch_count(this._index, key, out IntPtr error));
+            HandleError(error);
+            return count;
+        }
+
+        private void IncreaseCapacity(ulong size)
+        {
+            usearch_reserve(this._index, (UIntPtr)(this.Size() + size), out IntPtr error);
+            HandleError(error);
+        }
+
+        private void CheckIncreaseCapacity(ulong size_increase)
+        {
+            ulong size_demand = this.Size() + size_increase;
+            if (this.Capacity() < size_demand)
+            {
+                this.IncreaseCapacity(size_increase);
+            }
+        }
+
+        public void Add(ulong key, float[] vector)
+        {
+            this.CheckIncreaseCapacity(1);
+            usearch_add(this._index, key, vector, ScalarKind.Float32, out IntPtr error);
+            HandleError(error);
+        }
+
+        public void Add(ulong key, double[] vector)
+        {
+            this.CheckIncreaseCapacity(1);
+            usearch_add(this._index, key, vector, ScalarKind.Float64, out IntPtr error);
+            HandleError(error);
+        }
+
+        public void Add(ulong[] keys, float[][] vectors)
+        {
+            this.CheckIncreaseCapacity((ulong)vectors.Length);
+            for (int i = 0; i < vectors.Length; i++)
+            {
+                usearch_add(this._index, keys[i], vectors[i], ScalarKind.Float32, out IntPtr error);
+                HandleError(error);
+            }
+        }
+
+        public void Add(ulong[] keys, double[][] vectors)
+        {
+            this.CheckIncreaseCapacity((ulong)vectors.Length);
+            for (int i = 0; i < vectors.Length; i++)
+            {
+                usearch_add(this._index, keys[i], vectors[i], ScalarKind.Float64, out IntPtr error);
+                HandleError(error);
+            }
+        }
+
+        public int Get(ulong key, out float[] vector)
+        {
+            vector = new float[this._cachedDimensions];
+            int foundVectorsCount = checked((int)usearch_get(this._index, key, (UIntPtr)1, vector, ScalarKind.Float32, out IntPtr error));
+            HandleError(error);
+            if (foundVectorsCount < 1)
+            {
+                vector = null;
+            }
+
+            return foundVectorsCount;
+        }
+
+        public int Get(ulong key, int count, out float[][] vectors)
+        {
+            var flattenVectors = new float[count * (int)this._cachedDimensions];
+            int foundVectorsCount = checked((int)usearch_get(this._index, key, (UIntPtr)count, flattenVectors, ScalarKind.Float32, out IntPtr error));
+            HandleError(error);
+            if (foundVectorsCount < 1)
+            {
+                vectors = null;
+            }
+            else
+            {
+                vectors = new float[foundVectorsCount][];
+                for (int i = 0; i < foundVectorsCount; i++)
+                {
+                    vectors[i] = new float[this._cachedDimensions];
+                    Array.Copy(flattenVectors, i * (int)this._cachedDimensions, vectors[i], 0, (int)this._cachedDimensions);
+                }
+            }
+
+            return foundVectorsCount;
+        }
+
+        public int Get(ulong key, out double[] vector)
+        {
+            vector = new double[this._cachedDimensions];
+            int foundVectorsCount = checked((int)usearch_get(this._index, key, (UIntPtr)1, vector, ScalarKind.Float64, out IntPtr error));
+            HandleError(error);
+            if (foundVectorsCount < 1)
+            {
+                vector = null;
+            }
+
+            return foundVectorsCount;
+        }
+
+        public int Get(ulong key, int count, out double[][] vectors)
+        {
+            var flattenVectors = new double[count * (int)this._cachedDimensions];
+            int foundVectorsCount = checked((int)usearch_get(this._index, key, (UIntPtr)count, flattenVectors, ScalarKind.Float64, out IntPtr error));
+            HandleError(error);
+            if (foundVectorsCount < 1)
+            {
+                vectors = null;
+            }
+            else
+            {
+                vectors = new double[foundVectorsCount][];
+                for (int i = 0; i < foundVectorsCount; i++)
+                {
+                    vectors[i] = new double[this._cachedDimensions];
+                    Array.Copy(flattenVectors, i * (int)this._cachedDimensions, vectors[i], 0, (int)this._cachedDimensions);
+                }
+            }
+
+            return foundVectorsCount;
+        }
+
+        public int Remove(ulong key)
+        {
+            int removedCount = checked((int)usearch_remove(this._index, key, out IntPtr error));
+            HandleError(error);
+            return removedCount;
+        }
+
+        public int Rename(ulong keyFrom, ulong keyTo)
+        {
+            int foundVectorsCount = checked((int)usearch_rename(this._index, keyFrom, keyTo, out IntPtr error));
+            HandleError(error);
+            return foundVectorsCount;
+        }
+
+        private static void HandleError(IntPtr error)
+        {
+            if (error != IntPtr.Zero)
+            {
+                throw new USearchException($"USearch operation failed: {Marshal.PtrToStringAnsi(error)}");
+            }
+        }
+
+        private void FreeIndex()
+        {
+            if (this._index != IntPtr.Zero)
+            {
+                usearch_free(this._index, out IntPtr error);
+                HandleError(error);
+                this._index = IntPtr.Zero;
+            }
+        }
+
+        public void Dispose()
+        {
+            this.Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!this._disposedValue)
+            {
+                this.FreeIndex();
+                this._disposedValue = true;
+            }
+        }
+
+        ~USearchIndex() => this.Dispose(false);
+
+        //========================== Additional methods from LLMUnity ==========================//
+
+        public static Func<int, int> FilterFunction;
+
+        private static readonly object filterLock = new object();
+
+        [MonoPInvokeCallback(typeof(NativeMethods.FilterCallback))]
+        public static int StaticFilter(int key, System.IntPtr filterState)
+        {
+            if (FilterFunction != null) return FilterFunction(key);
+            return 1;
+        }
+
+        private int Search<T>(T[] queryVector, int count, out ulong[] keys, out float[] distances, ScalarKind scalarKind, Func<int, int> filter = null)
+        {
+            keys = new ulong[count];
+            distances = new float[count];
+
+            GCHandle handle = GCHandle.Alloc(queryVector, GCHandleType.Pinned);
+            int matches = 0;
+            try
+            {
+                IntPtr queryVectorPtr = handle.AddrOfPinnedObject();
+                IntPtr error;
+                if (filter == null)
+                {
+                    matches = checked((int)usearch_search(this._index, queryVectorPtr, scalarKind, (UIntPtr)count, keys, distances, out error));
+                }
+                else
+                {
+                    if (Application.platform == RuntimePlatform.Android)
+                    {
+                        lock (filterLock)
+                        {
+                            FilterFunction = filter;
+                            matches = checked((int)usearch_filtered_search(this._index, queryVectorPtr, scalarKind, (UIntPtr)count, StaticFilter, IntPtr.Zero, keys, distances, out error));
+                        }
+                    }
+                    else
+                    {
+                        matches = checked((int)usearch_filtered_search(this._index, queryVectorPtr, scalarKind, (UIntPtr)count, (int key, IntPtr state) => filter(key), IntPtr.Zero, keys, distances, out error));
+                    }
+                }
+                HandleError(error);
+            }
+            finally
+            {
+                handle.Free();
+            }
+
+            if (matches < count)
+            {
+                Array.Resize(ref keys, (int)matches);
+                Array.Resize(ref distances, (int)matches);
+            }
+
+            return matches;
+        }
+
+        public int Search(float[] queryVector, int count, out ulong[] keys, out float[] distances, Func<int, int> filter = null)
+        {
+            return this.Search(queryVector, count, out keys, out distances, ScalarKind.Float32, filter);
+        }
+
+        public int Search(double[] queryVector, int count, out ulong[] keys, out float[] distances, Func<int, int> filter = null)
+        {
+            return this.Search(queryVector, count, out keys, out distances, ScalarKind.Float64, filter);
+        }
+
+        protected virtual string GetIndexFilename()
+        {
+            return "usearch/index";
+        }
+
+        public void Save(ZipArchive zipArchive)
+        {
+            string indexPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
+            Save(indexPath);
+            try
+            {
+                zipArchive.CreateEntryFromFile(indexPath, GetIndexFilename());
+            }
+            catch (Exception ex)
+            {
+                Debug.LogError($"Error adding file to the zip archive: {ex.Message}");
+            }
+            File.Delete(indexPath);
+        }
+
+        public void Load(ZipArchive zipArchive)
+        {
+            IndexOptions initOptions = new();
+            this._index = usearch_init(ref initOptions, out IntPtr error);
+            HandleError(error);
+
+            try
+            {
+                ZipArchiveEntry entry = zipArchive.GetEntry(GetIndexFilename());
+                using (Stream entryStream = entry.Open())
+                using (MemoryStream memoryStream = new MemoryStream())
+                {
+                    entryStream.CopyTo(memoryStream);
+                    // Access the length and create a buffer
+                    byte[] managedBuffer = new byte[memoryStream.Length];
+                    memoryStream.Position = 0;  // Reset the position to the beginning
+                    memoryStream.Read(managedBuffer, 0, managedBuffer.Length);
+
+                    GCHandle handle = GCHandle.Alloc(managedBuffer, GCHandleType.Pinned);
+                    try
+                    {
+                        IntPtr unmanagedBuffer = handle.AddrOfPinnedObject();
+                        usearch_load_buffer(_index, unmanagedBuffer, (UIntPtr)managedBuffer.Length, out error);
+                        HandleError(error);
+                    }
+                    finally
+                    {
+                        handle.Free();
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                Debug.LogError($"Error loading the search index: {ex.Message}");
+            }
+
+            this._cachedDimensions = this.Dimensions();
+        }
+    }
+}
diff --git a/Runtime/RAG/usearch/USearchIndex.cs.meta b/Runtime/RAG/usearch/USearchIndex.cs.meta
new file mode 100644
index 00000000..623202bf
--- /dev/null
+++ b/Runtime/RAG/usearch/USearchIndex.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bc9f068a1a8eab16fad8f42e4b0b013e
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/RAG/usearch/USearchTypes.cs b/Runtime/RAG/usearch/USearchTypes.cs
new file mode 100644
index 00000000..c780181b
--- /dev/null
+++ b/Runtime/RAG/usearch/USearchTypes.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Cloud.Unum.USearch
+{
+    public enum MetricKind : uint
+    {
+        Unknown = 0,
+        Cos,
+        Ip,
+        L2sq,
+        Haversine,
+        Pearson,
+        Jaccard,
+        Hamming,
+        Tanimoto,
+        Sorensen,
+    }
+
+    public enum ScalarKind : uint
+    {
+        Unknown = 0,
+        Float32,
+        Float64,
+        Float16,
+        Int8,
+        Byte1,
+    }
+
+    // TODO: implement custom metric delegate
+    // Microsoft guides links:
+    // 1) https://learn.microsoft.com/en-us/dotnet/standard/native-interop/best-practices
+    // 2) https://learn.microsoft.com/en-us/dotnet/framework/interop/marshalling-a-delegate-as-a-callback-method
+    // public delegate float CustomMetricFunction(IntPtr a, IntPtr b);
+
+    [Serializable]
+    [StructLayout(LayoutKind.Sequential)]
+    public struct IndexOptions
+    {
+        public MetricKind metric_kind;
+        public IntPtr metric;
+        public ScalarKind quantization;
+        public ulong dimensions;
+        public ulong connectivity;
+        public ulong expansion_add;
+        public ulong expansion_search;
+
+        [MarshalAs(UnmanagedType.Bool)]
+        public bool multi;
+
+        public IndexOptions(
+            MetricKind metricKind = MetricKind.Unknown,
+            IntPtr metric = default,
+            ScalarKind quantization = ScalarKind.Unknown,
+            ulong dimensions = 0,
+            ulong connectivity = 0,
+            ulong expansionAdd = 0,
+            ulong expansionSearch = 0,
+            bool multi = false
+        )
+        {
+            this.metric_kind = metricKind;
+            this.metric = default; // TODO: Use actual metric param, when support is added for custom metric delegate
+            this.quantization = quantization;
+            this.dimensions = dimensions;
+            this.connectivity = connectivity;
+            this.expansion_add = expansionAdd;
+            this.expansion_search = expansionSearch;
+            this.multi = multi;
+        }
+    }
+}
diff --git a/Runtime/RAG/usearch/USearchTypes.cs.meta b/Runtime/RAG/usearch/USearchTypes.cs.meta
new file mode 100644
index 00000000..5e16b24c
--- /dev/null
+++ b/Runtime/RAG/usearch/USearchTypes.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cb3a11c4f75b85afea970e466d0f3120
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Runtime/ResumingWebClient.cs b/Runtime/ResumingWebClient.cs
index b282caa2..fc299758 100644
--- a/Runtime/ResumingWebClient.cs
+++ b/Runtime/ResumingWebClient.cs
@@ -1,3 +1,5 @@
+/// @file
+/// @brief File implementing a resumable Web client
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -7,6 +9,10 @@
 
 namespace LLMUnity
 {
+    /// @ingroup utils
+    /// <summary>
+    /// Class implementing a resumable Web client
+    /// </summary>
     public class ResumingWebClient : WebClient
     {
         private const int timeoutMs = 30 * 1000;
diff --git a/Runtime/undream.llmunity.Runtime.asmdef b/Runtime/undream.llmunity.Runtime.asmdef
index 140aec56..800db04c 100644
--- a/Runtime/undream.llmunity.Runtime.asmdef
+++ b/Runtime/undream.llmunity.Runtime.asmdef
@@ -1,3 +1,6 @@
 {
-    "name": "undream.llmunity.Runtime"
+    "name": "undream.llmunity.Runtime",
+    "references": [
+        "Cloud.Unum.USearch"
+    ]
 }
\ No newline at end of file
diff --git a/Samples~/KnowledgeBaseGame/Dialogues/.~lock.butler.csv# b/Samples~/KnowledgeBaseGame/Dialogues/.~lock.butler.csv#
new file mode 100644
index 00000000..2e9699b1
--- /dev/null
+++ b/Samples~/KnowledgeBaseGame/Dialogues/.~lock.butler.csv#
@@ -0,0 +1 @@
+,benuix,benuix-laptop,30.10.2024 13:05,file:///home/benuix/.config/libreoffice/4;
\ No newline at end of file
diff --git a/Samples~/KnowledgeBaseGame/KnowledgeBase.asmdef b/Samples~/KnowledgeBaseGame/KnowledgeBase.asmdef
deleted file mode 100644
index e8831c36..00000000
--- a/Samples~/KnowledgeBaseGame/KnowledgeBase.asmdef
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-    "name": "KnowledgeBase",
-    "rootNamespace": "",
-    "references": [
-        "undream.llmunity.Runtime",
-        "undream.RAGSearchUnity.Runtime",
-        "Unity.Sentis",
-        "HuggingFace.SharpTransformers",
-        "Cloud.Unum.USearch"
-    ],
-    "includePlatforms": [],
-    "excludePlatforms": [],
-    "allowUnsafeCode": false,
-    "overrideReferences": false,
-    "precompiledReferences": [],
-    "autoReferenced": true,
-    "defineConstraints": [
-        "RAGSEARCHUNITY"
-    ],
-    "versionDefines": [
-        {
-            "name": "ai.undream.ragsearchunity",
-            "expression": "1.0.0",
-            "define": "RAGSEARCHUNITY"
-        }
-    ],
-    "noEngineReferences": false
-}
\ No newline at end of file
diff --git a/Samples~/KnowledgeBaseGame/KnowledgeBaseGame.cs b/Samples~/KnowledgeBaseGame/KnowledgeBaseGame.cs
index e6f3bc29..3bd1d284 100644
--- a/Samples~/KnowledgeBaseGame/KnowledgeBaseGame.cs
+++ b/Samples~/KnowledgeBaseGame/KnowledgeBaseGame.cs
@@ -4,55 +4,90 @@
 using System.Diagnostics;
 using Debug = UnityEngine.Debug;
 using UnityEngine.UI;
-using System.Collections;
-using RAGSearchUnity;
 using LLMUnity;
+using System.Threading.Tasks;
+using System.Linq;
+using System;
 
 namespace LLMUnitySamples
 {
-    public class Bot
+    public class KnowledgeBaseGame : KnowledgeBaseGameUI
     {
-        Dictionary<string, string> dialogues;
-        SearchEngine search;
+        [Header("Models")]
+        public LLMCharacter llmCharacter;
+        public RAG rag;
+        public int numRAGResults = 3;
+
+        string ragPath = "KnowledgeBaseGame.zip";
+        Dictionary<string, Dictionary<string, string>> botQuestionAnswers = new Dictionary<string, Dictionary<string, string>>();
+        Dictionary<string, RawImage> botImages = new Dictionary<string, RawImage>();
+        string currentBotName;
+
+        new async void Start()
+        {
+            base.Start();
+            CheckLLMs(false);
+            InitElements();
+            await InitRAG();
+            InitLLM();
+        }
+
+        void InitElements()
+        {
+            PlayerText.interactable = false;
+            botImages["Butler"] = ButlerImage;
+            botImages["Maid"] = MaidImage;
+            botImages["Chef"] = ChefImage;
+            botQuestionAnswers["Butler"] = LoadQuestionAnswers(ButlerText.text);
+            botQuestionAnswers["Maid"] = LoadQuestionAnswers(MaidText.text);
+            botQuestionAnswers["Chef"] = LoadQuestionAnswers(ChefText.text);
+        }
+
+        async Task InitRAG()
+        {
+            // create the embeddings
+            await CreateEmbeddings();
+            DropdownChange(CharacterSelect.value);
+        }
 
-        public Bot(string dialogueText, EmbeddingModel model, string embeddingsPath)
+        void InitLLM()
         {
-            LoadDialogues(dialogueText);
-            CreateEmbeddings(model, embeddingsPath);
+            // warm-up the LLM
+            PlayerText.text += "Warming up the model...";
+            _ = llmCharacter.Warmup(AIReplyComplete);
         }
 
-        void LoadDialogues(string dialogueText)
+        public Dictionary<string, string> LoadQuestionAnswers(string questionAnswersText)
         {
-            dialogues = new Dictionary<string, string>();
-            foreach (string line in dialogueText.Split("\n"))
+            Dictionary<string, string> questionAnswers = new Dictionary<string, string>();
+            foreach (string line in questionAnswersText.Split("\n"))
             {
                 if (line == "") continue;
                 string[] lineParts = line.Split("|");
-                dialogues[lineParts[0]] = lineParts[1];
+                questionAnswers[lineParts[0]] = lineParts[1];
             }
+            return questionAnswers;
         }
 
-        void CreateEmbeddings(EmbeddingModel model, string embeddingsPath)
+        public async Task CreateEmbeddings()
         {
-            if (File.Exists(embeddingsPath))
-            {
-                // load the embeddings
-                search = SearchEngine.Load(model, embeddingsPath);
-            }
-            else
+            bool loaded = await rag.Load(ragPath);
+            if (!loaded)
             {
     #if UNITY_EDITOR
-                search = new SearchEngine(model);
                 Stopwatch stopwatch = new Stopwatch();
-                stopwatch.Start();
                 // build the embeddings
-                foreach (string question in dialogues.Keys)
+                foreach ((string botName, Dictionary<string, string> botQuestionAnswers) in botQuestionAnswers)
                 {
-                    search.Add(question);
+                    PlayerText.text += $"Creating Embeddings for {botName} (only once)...\n";
+                    List<string> questions = botQuestionAnswers.Keys.ToList();
+                    stopwatch.Start();
+                    foreach (string question in questions) await rag.Add(question, botName);
+                    stopwatch.Stop();
+                    Debug.Log($"embedded {rag.Count()} phrases in {stopwatch.Elapsed.TotalMilliseconds / 1000f} secs");
                 }
-                Debug.Log($"embedded {search.NumPhrases()} phrases, {search.NumSentences()} sentences in {stopwatch.Elapsed.TotalMilliseconds / 1000f} secs");
                 // store the embeddings
-                search.Save(embeddingsPath);
+                rag.Save(ragPath);
     #else
                 // if in play mode throw an error
                 throw new System.Exception("The embeddings could not be found!");
@@ -60,89 +95,44 @@ void CreateEmbeddings(EmbeddingModel model, string embeddingsPath)
             }
         }
 
-        public List<string> Retrieval(string question)
+        public async Task<List<string>> Retrieval(string question)
         {
-            string[] similarQuestions = search.Search(question, 3);
+            // find similar questions for the current bot using the RAG
+            (string[] similarQuestions, _) = await rag.Search(question, numRAGResults, currentBotName);
+            // get the answers of the similar questions
             List<string> similarAnswers = new List<string>();
-            foreach (string similarQuestion in similarQuestions) similarAnswers.Add(dialogues[similarQuestion]);
+            foreach (string similarQuestion in similarQuestions) similarAnswers.Add(botQuestionAnswers[currentBotName][similarQuestion]);
             return similarAnswers;
         }
 
-        public int NumPhrases()
+        public async Task<string> ConstructPrompt(string question)
         {
-            return search.NumPhrases();
+            // get similar answers from the RAG
+            List<string> similarAnswers = await Retrieval(question);
+            // create the prompt using the user question and the similar answers
+            string answers = "";
+            foreach (string similarAnswer in similarAnswers) answers += $"\n- {similarAnswer}";
+            // string prompt = $"Robot: {currentBotName}\n\n";
+            string prompt = $"Question: {question}\n\n";
+            prompt += $"Possible Answers: {answers}";
+            return prompt;
         }
-    }
 
-    public class KnowledgeBaseGame : KnowledgeBaseGameUI
-    {
-        public LLMCharacter llmCharacter;
-        public Embedding embedding;
-
-        Dictionary<string, Bot> bots = new Dictionary<string, Bot>();
-        Dictionary<string, RawImage> botImages = new Dictionary<string, RawImage>();
-        string currentBotName;
-        Bot currentBot;
-        RawImage currentImage;
-        List<(string botName, TextAsset asset, RawImage image)> botInfo;
-
-        new void Start()
-        {
-            base.Start();
-            botInfo = new List<(string botName, TextAsset asset, RawImage image)>()
-            {
-                ("Butler", ButlerText, ButlerImage),
-                ("Maid", MaidText, MaidImage),
-                ("Chef", ChefText, ChefImage)
-            };
-            StartCoroutine(InitModels());
-        }
-
-        IEnumerator InitModels()
-        {
-            PlayerText.interactable = false;
-            yield return null;
-            string outputDir = Path.Combine(Application.streamingAssetsPath, "KnowledgeBaseGame");
-            if (!Directory.Exists(outputDir)) Directory.CreateDirectory(outputDir);
-
-            // init the bots with the embeddings
-            EmbeddingModel model = embedding.GetModel();
-            if (model == null) throw new System.Exception("Please select a model in the Embedding GameObject!");
-            foreach ((string botName, TextAsset asset, RawImage image) in botInfo)
-            {
-                string embeddingsPath = Path.Combine(outputDir, botName + ".zip");
-                PlayerText.text += File.Exists(embeddingsPath) ? $"Loading {botName} dialogues...\n" : $"Creating Embeddings for {botName} (only once)...\n";
-                yield return null;
-                bots[botName] = new Bot(asset.text, model, embeddingsPath);
-                botImages[botName] = image;
-            }
-
-            // warm-up the LLM
-            PlayerText.text += "Warming up the model...";
-            _ = llmCharacter.Warmup(AIReplyComplete);
-
-            DropdownChange(CharacterSelect.value);
-            yield return null;
-        }
-
-        protected override void OnInputFieldSubmit(string question)
+        protected async override void OnInputFieldSubmit(string question)
         {
             PlayerText.interactable = false;
-            List<string> similarAnswers = currentBot.Retrieval(question);
-            string prompt = $"Question:\n{question}\n\nAnswers:\n";
-            foreach (string similarAnswer in similarAnswers) prompt += $"- {similarAnswer}\n";
+            SetAIText("...");
+            string prompt = await ConstructPrompt(question);
             _ = llmCharacter.Chat(prompt, SetAIText, AIReplyComplete);
         }
 
         protected override void DropdownChange(int selection)
         {
             // select another character
+            if (!String.IsNullOrEmpty(currentBotName)) botImages[currentBotName].gameObject.SetActive(false);
             currentBotName = CharacterSelect.options[selection].text;
-            currentBot = bots[currentBotName];
-            if (currentImage != null) currentImage.gameObject.SetActive(false);
-            currentImage = botImages[currentBotName];
-            currentImage.gameObject.SetActive(true);
-            Debug.Log($"{currentBotName}: {currentBot.NumPhrases()} phrases available");
+            botImages[currentBotName].gameObject.SetActive(true);
+            Debug.Log($"{currentBotName}: {rag.Count(currentBotName)} phrases available");
 
             // set the LLMCharacter name
             llmCharacter.AIName = currentBotName;
@@ -172,13 +162,28 @@ public void ExitGame()
             Application.Quit();
         }
 
+        void CheckLLM(LLMCaller llmCaller, bool debug)
+        {
+            if (!llmCaller.remote && llmCaller.llm != null && llmCaller.llm.model == "")
+            {
+                string error = $"Please select a llm model in the {llmCaller.llm.gameObject.name} GameObject!";
+                if (debug) Debug.LogWarning(error);
+                else throw new System.Exception(error);
+            }
+        }
+
+        void CheckLLMs(bool debug)
+        {
+            CheckLLM(rag.search.llmEmbedder, debug);
+            CheckLLM(llmCharacter, debug);
+        }
+
         bool onValidateWarning = true;
         void OnValidate()
         {
             if (onValidateWarning)
             {
-                if (embedding.SelectedOption == 0) Debug.LogWarning($"Please select a model in the {embedding.gameObject.name} GameObject!");
-                if (!llmCharacter.remote && llmCharacter.llm != null && llmCharacter.llm.model == "") Debug.LogWarning($"Please select a model in the {llmCharacter.llm.gameObject.name} GameObject!");
+                CheckLLMs(true);
                 onValidateWarning = false;
             }
         }
@@ -186,41 +191,40 @@ void OnValidate()
 
     public class KnowledgeBaseGameUI : MonoBehaviour
     {
+        [Header("UI elements")]
         public Dropdown CharacterSelect;
         public InputField PlayerText;
-        public Text SetupText;
         public Text AIText;
 
+        [Header("Bot texts")]
         public TextAsset ButlerText;
         public TextAsset MaidText;
         public TextAsset ChefText;
+
+        [Header("Bot images")]
         public RawImage ButlerImage;
         public RawImage MaidImage;
         public RawImage ChefImage;
 
+        [Header("Buttons")]
         public Button NotesButton;
         public Button MapButton;
         public Button SolveButton;
         public Button HelpButton;
+        public Button SubmitButton;
 
+        [Header("Panels")]
         public RawImage NotebookImage;
         public GameObject NotesPanel;
         public GameObject SolvePanel;
         public GameObject HelpPanel;
-
         public RawImage MapImage;
-        public Button SubmitButton;
         public RawImage SuccessImage;
         public Text FailText;
         public Dropdown Answer1;
         public Dropdown Answer2;
         public Dropdown Answer3;
 
-        void Awake()
-        {
-            if (SetupText != null) SetupText.gameObject.SetActive(false);
-        }
-
         protected void Start()
         {
             AddListeners();
diff --git a/Samples~/KnowledgeBaseGame/Scene.unity b/Samples~/KnowledgeBaseGame/Scene.unity
index 8d252123..2fc2bc21 100644
--- a/Samples~/KnowledgeBaseGame/Scene.unity
+++ b/Samples~/KnowledgeBaseGame/Scene.unity
@@ -1025,7 +1025,6 @@ MonoBehaviour:
   m_EditorClassIdentifier: 
   CharacterSelect: {fileID: 1821864875}
   PlayerText: {fileID: 283994679}
-  SetupText: {fileID: 2024418435}
   AIText: {fileID: 681685488}
   ButlerText: {fileID: 4900000, guid: c2c64001c142dfdbab3c68bbf78335ed, type: 3}
   MaidText: {fileID: 4900000, guid: 70839d4b753f9ff66a48a0d931db2629, type: 3}
@@ -1037,19 +1036,20 @@ MonoBehaviour:
   MapButton: {fileID: 692572909}
   SolveButton: {fileID: 1023571710}
   HelpButton: {fileID: 1696547302}
+  SubmitButton: {fileID: 964505547}
   NotebookImage: {fileID: 828313583}
   NotesPanel: {fileID: 1301879205}
   SolvePanel: {fileID: 1260794225}
   HelpPanel: {fileID: 1385587314}
   MapImage: {fileID: 964460963}
-  SubmitButton: {fileID: 964505547}
   SuccessImage: {fileID: 1723006218}
   FailText: {fileID: 1626244059}
   Answer1: {fileID: 1290124570}
   Answer2: {fileID: 504847329}
   Answer3: {fileID: 1278063795}
   llmCharacter: {fileID: 1275496423}
-  embedding: {fileID: 1772403371}
+  rag: {fileID: 1400265393}
+  numRAGResults: 3
 --- !u!1 &495835622
 GameObject:
   m_ObjectHideFlags: 0
@@ -2028,6 +2028,75 @@ CanvasRenderer:
   m_PrefabAsset: {fileID: 0}
   m_GameObject: {fileID: 744895509}
   m_CullTransparentMesh: 1
+--- !u!1 &758599401
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 758599403}
+  - component: {fileID: 758599402}
+  m_Layer: 0
+  m_Name: LLMRAG
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &758599402
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 758599401}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: a50e3140c3ecaaf1c848dbf141cc2074, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  advancedOptions: 0
+  remote: 0
+  port: 13333
+  numThreads: -1
+  numGPULayers: 0
+  debug: 0
+  parallelPrompts: -1
+  dontDestroyOnLoad: 1
+  contextSize: 8192
+  batchSize: 512
+  basePrompt: 
+  model: 
+  chatTemplate: chatml
+  lora: 
+  loraWeights: 
+  flashAttention: 0
+  APIKey: 
+  SSLCert: 
+  SSLCertPath: 
+  SSLKey: 
+  SSLKeyPath: 
+  minContextLength: 0
+  maxContextLength: 0
+  embeddingsOnly: 0
+  embeddingLength: 0
+--- !u!4 &758599403
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 758599401}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 887.5697, y: 599.9278, z: -4.22581}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
 --- !u!1 &805977037
 GameObject:
   m_ObjectHideFlags: 0
@@ -2857,7 +2926,6 @@ RectTransform:
   - {fileID: 964460962}
   - {fileID: 1723006217}
   - {fileID: 1468962045}
-  - {fileID: 2024418434}
   m_Father: {fileID: 0}
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_AnchorMin: {x: 0, y: 0}
@@ -4281,18 +4349,17 @@ MonoBehaviour:
   m_EditorClassIdentifier: 
   advancedOptions: 0
   remote: 0
-  llm: {fileID: 2142407556}
+  _llm: {fileID: 2142407556}
+  APIKey: 
   host: localhost
   port: 13333
   numRetries: 10
-  APIKey: 
   save: 
   saveCache: 0
   debugPrompt: 0
-  stream: 1
+  slot: -1
   grammar: 
   cachePrompt: 1
-  slot: -1
   seed: 0
   numPredict: 256
   temperature: 0.2
@@ -4314,16 +4381,11 @@ MonoBehaviour:
   ignoreEos: 0
   nKeep: -1
   stop: []
-  playerName: Detective
-  AIName: 
-  prompt: 'You are a robot working at a house where a diamond was stolen and a detective
-    asks you questions about the robbery.
-
-    Answer the question provided at the
-    section "Question" based on the possible answers at the section "Answers".
-
-    Rephrase
-    the answer, do not copy it directly.'
+  stream: 1
+  playerName: user
+  AIName: assistant
+  prompt: A chat between a curious human and an artificial intelligence assistant.
+    The assistant gives helpful, detailed, and polite answers to the human's questions.
   setNKeepToPrompt: 1
   chat: []
   grammarString: 
@@ -5104,6 +5166,112 @@ CanvasRenderer:
   m_PrefabAsset: {fileID: 0}
   m_GameObject: {fileID: 1388328534}
   m_CullTransparentMesh: 1
+--- !u!1 &1400265384
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1400265389}
+  - component: {fileID: 1400265393}
+  - component: {fileID: 1400265392}
+  - component: {fileID: 1400265395}
+  - component: {fileID: 1400265394}
+  m_Layer: 0
+  m_Name: RAG
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &1400265389
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1400265384}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 889.47327, y: 795.4123, z: -7.038724}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1400265392
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1400265384}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: c6856fbefac554a38a7b8a4b353fd43d, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  advancedOptions: 0
+  remote: 0
+  _llm: {fileID: 758599402}
+  APIKey: 
+  host: localhost
+  port: 13333
+  numRetries: 10
+--- !u!114 &1400265393
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1400265384}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: a2496546d1575771597fc8cbdd0d852d, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  searchClass: 1
+  search: {fileID: 1400265395}
+  chunkingClass: 3
+  chunking: {fileID: 1400265394}
+  preSearchClass: 0
+  preChunkingClass: 0
+--- !u!114 &1400265394
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1400265384}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 354c2418b0d6913efbfb73dccd540d23, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  search: {fileID: 1400265395}
+  returnChunks: 0
+  delimiters: 2e0021003a003b003f000a000d00
+--- !u!114 &1400265395
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1400265384}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: f8c6492f8c97ab9a09b0eb0f93a158da, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  llmEmbedder: {fileID: 1400265392}
+  advancedOptions: 0
+  quantization: 3
+  metricKind: 1
+  connectivity: 32
+  expansionAdd: 40
+  expansionSearch: 16
 --- !u!1 &1468962044
 GameObject:
   m_ObjectHideFlags: 0
@@ -6239,52 +6407,6 @@ CanvasRenderer:
   m_PrefabAsset: {fileID: 0}
   m_GameObject: {fileID: 1766894170}
   m_CullTransparentMesh: 1
---- !u!1 &1772403370
-GameObject:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  serializedVersion: 6
-  m_Component:
-  - component: {fileID: 1772403372}
-  - component: {fileID: 1772403371}
-  m_Layer: 0
-  m_Name: Embedding
-  m_TagString: Untagged
-  m_Icon: {fileID: 0}
-  m_NavMeshLayer: 0
-  m_StaticEditorFlags: 0
-  m_IsActive: 1
---- !u!114 &1772403371
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1772403370}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: a329c2b464600fb51a49b46dde889482, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
-  SelectedOption: 0
-  downloadProgress: 1
---- !u!4 &1772403372
-Transform:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1772403370}
-  serializedVersion: 2
-  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
-  m_LocalPosition: {x: 0, y: 0, z: 0}
-  m_LocalScale: {x: 1, y: 1, z: 1}
-  m_ConstrainProportionsScale: 0
-  m_Children: []
-  m_Father: {fileID: 0}
-  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
 --- !u!1 &1807881543
 GameObject:
   m_ObjectHideFlags: 0
@@ -7241,87 +7363,6 @@ CanvasRenderer:
   m_PrefabAsset: {fileID: 0}
   m_GameObject: {fileID: 2019606177}
   m_CullTransparentMesh: 1
---- !u!1 &2024418433
-GameObject:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  serializedVersion: 6
-  m_Component:
-  - component: {fileID: 2024418434}
-  - component: {fileID: 2024418436}
-  - component: {fileID: 2024418435}
-  m_Layer: 5
-  m_Name: SetupText
-  m_TagString: Untagged
-  m_Icon: {fileID: 0}
-  m_NavMeshLayer: 0
-  m_StaticEditorFlags: 0
-  m_IsActive: 1
---- !u!224 &2024418434
-RectTransform:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 2024418433}
-  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
-  m_LocalPosition: {x: 0, y: 0, z: 0}
-  m_LocalScale: {x: 1, y: 1, z: 1}
-  m_ConstrainProportionsScale: 0
-  m_Children: []
-  m_Father: {fileID: 898411689}
-  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
-  m_AnchorMin: {x: 0.5, y: 0.5}
-  m_AnchorMax: {x: 0.5, y: 0.5}
-  m_AnchoredPosition: {x: -65.892715, y: -447.78424}
-  m_SizeDelta: {x: 1154.2146, y: 70}
-  m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &2024418435
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 2024418433}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
-  m_Material: {fileID: 0}
-  m_Color: {r: 1, g: 0, b: 0, a: 1}
-  m_RaycastTarget: 1
-  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
-  m_Maskable: 1
-  m_OnCullStateChanged:
-    m_PersistentCalls:
-      m_Calls: []
-  m_FontData:
-    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
-    m_FontSize: 30
-    m_FontStyle: 0
-    m_BestFit: 0
-    m_MinSize: 2
-    m_MaxSize: 40
-    m_Alignment: 0
-    m_AlignByGeometry: 0
-    m_RichText: 1
-    m_HorizontalOverflow: 0
-    m_VerticalOverflow: 0
-    m_LineSpacing: 1
-  m_Text: 'The sample requires the RAGSearchUnity asset from:
-
-    https://github.com/undreamai/RAGSearchUnity'
---- !u!222 &2024418436
-CanvasRenderer:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 2024418433}
-  m_CullTransparentMesh: 1
 --- !u!1 &2038337339
 GameObject:
   m_ObjectHideFlags: 0
@@ -7560,6 +7601,8 @@ MonoBehaviour:
   SSLKeyPath: 
   minContextLength: 0
   maxContextLength: 0
+  embeddingsOnly: 0
+  embeddingLength: 0
 --- !u!4 &2142407557
 Transform:
   m_ObjectHideFlags: 0
@@ -7664,7 +7707,8 @@ SceneRoots:
   - {fileID: 1535596278}
   - {fileID: 898411689}
   - {fileID: 862588794}
-  - {fileID: 1772403372}
   - {fileID: 2142407557}
+  - {fileID: 758599403}
+  - {fileID: 1400265389}
   - {fileID: 1275496424}
   - {fileID: 489627713}
diff --git a/Samples~/RAG.meta b/Samples~/RAG.meta
new file mode 100644
index 00000000..2140b3bb
--- /dev/null
+++ b/Samples~/RAG.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a91d30a8d944f7a73a6b9ba9b243b167
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Samples~/RAG/RAGAndLLM_Sample.cs b/Samples~/RAG/RAGAndLLM_Sample.cs
new file mode 100644
index 00000000..818324cd
--- /dev/null
+++ b/Samples~/RAG/RAGAndLLM_Sample.cs
@@ -0,0 +1,40 @@
+using UnityEngine.UI;
+using LLMUnity;
+
+namespace LLMUnitySamples
+{
+    public class RAGAndLLMSample : RAGSample
+    {
+        public LLMCharacter llmCharacter;
+        public Toggle ParaphraseWithLLM;
+
+        protected async override void onInputFieldSubmit(string message)
+        {
+            playerText.interactable = false;
+            AIText.text = "...";
+            (string[] similarPhrases, float[] distances) = await rag.Search(message, 1);
+            string similarPhrase = similarPhrases[0];
+            if (!ParaphraseWithLLM.isOn)
+            {
+                AIText.text = similarPhrase;
+                AIReplyComplete();
+            }
+            else
+            {
+                _ = llmCharacter.Chat("Paraphrase the following phrase: " + similarPhrase, SetAIText, AIReplyComplete);
+            }
+        }
+
+        public void CancelRequests()
+        {
+            llmCharacter.CancelRequests();
+            AIReplyComplete();
+        }
+
+        protected override void CheckLLMs(bool debug)
+        {
+            base.CheckLLMs(debug);
+            CheckLLM(llmCharacter, debug);
+        }
+    }
+}
diff --git a/Samples~/RAG/RAGAndLLM_Sample.cs.meta b/Samples~/RAG/RAGAndLLM_Sample.cs.meta
new file mode 100644
index 00000000..e24df422
--- /dev/null
+++ b/Samples~/RAG/RAGAndLLM_Sample.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fde8f7694420c760aabb639016d2d168
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Samples~/RAG/RAGAndLLM_Scene.unity b/Samples~/RAG/RAGAndLLM_Scene.unity
new file mode 100644
index 00000000..40756247
--- /dev/null
+++ b/Samples~/RAG/RAGAndLLM_Scene.unity
@@ -0,0 +1,2333 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!29 &1
+OcclusionCullingSettings:
+  m_ObjectHideFlags: 0
+  serializedVersion: 2
+  m_OcclusionBakeSettings:
+    smallestOccluder: 5
+    smallestHole: 0.25
+    backfaceThreshold: 100
+  m_SceneGUID: 00000000000000000000000000000000
+  m_OcclusionCullingData: {fileID: 0}
+--- !u!104 &2
+RenderSettings:
+  m_ObjectHideFlags: 0
+  serializedVersion: 9
+  m_Fog: 0
+  m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
+  m_FogMode: 3
+  m_FogDensity: 0.01
+  m_LinearFogStart: 0
+  m_LinearFogEnd: 300
+  m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
+  m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
+  m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
+  m_AmbientIntensity: 1
+  m_AmbientMode: 0
+  m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
+  m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
+  m_HaloStrength: 0.5
+  m_FlareStrength: 1
+  m_FlareFadeSpeed: 3
+  m_HaloTexture: {fileID: 0}
+  m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
+  m_DefaultReflectionMode: 0
+  m_DefaultReflectionResolution: 128
+  m_ReflectionBounces: 1
+  m_ReflectionIntensity: 1
+  m_CustomReflection: {fileID: 0}
+  m_Sun: {fileID: 0}
+  m_IndirectSpecularColor: {r: 0.44657832, g: 0.49641222, b: 0.57481664, a: 1}
+  m_UseRadianceAmbientProbe: 0
+--- !u!157 &3
+LightmapSettings:
+  m_ObjectHideFlags: 0
+  serializedVersion: 12
+  m_GIWorkflowMode: 1
+  m_GISettings:
+    serializedVersion: 2
+    m_BounceScale: 1
+    m_IndirectOutputScale: 1
+    m_AlbedoBoost: 1
+    m_EnvironmentLightingMode: 0
+    m_EnableBakedLightmaps: 1
+    m_EnableRealtimeLightmaps: 0
+  m_LightmapEditorSettings:
+    serializedVersion: 12
+    m_Resolution: 2
+    m_BakeResolution: 40
+    m_AtlasSize: 1024
+    m_AO: 0
+    m_AOMaxDistance: 1
+    m_CompAOExponent: 1
+    m_CompAOExponentDirect: 0
+    m_ExtractAmbientOcclusion: 0
+    m_Padding: 2
+    m_LightmapParameters: {fileID: 0}
+    m_LightmapsBakeMode: 1
+    m_TextureCompression: 1
+    m_FinalGather: 0
+    m_FinalGatherFiltering: 1
+    m_FinalGatherRayCount: 256
+    m_ReflectionCompression: 2
+    m_MixedBakeMode: 2
+    m_BakeBackend: 1
+    m_PVRSampling: 1
+    m_PVRDirectSampleCount: 32
+    m_PVRSampleCount: 512
+    m_PVRBounces: 2
+    m_PVREnvironmentSampleCount: 256
+    m_PVREnvironmentReferencePointCount: 2048
+    m_PVRFilteringMode: 1
+    m_PVRDenoiserTypeDirect: 1
+    m_PVRDenoiserTypeIndirect: 1
+    m_PVRDenoiserTypeAO: 1
+    m_PVRFilterTypeDirect: 0
+    m_PVRFilterTypeIndirect: 0
+    m_PVRFilterTypeAO: 0
+    m_PVREnvironmentMIS: 1
+    m_PVRCulling: 1
+    m_PVRFilteringGaussRadiusDirect: 1
+    m_PVRFilteringGaussRadiusIndirect: 5
+    m_PVRFilteringGaussRadiusAO: 2
+    m_PVRFilteringAtrousPositionSigmaDirect: 0.5
+    m_PVRFilteringAtrousPositionSigmaIndirect: 2
+    m_PVRFilteringAtrousPositionSigmaAO: 1
+    m_ExportTrainingData: 0
+    m_TrainingDataDestination: TrainingData
+    m_LightProbeSampleCountMultiplier: 4
+  m_LightingDataAsset: {fileID: 0}
+  m_LightingSettings: {fileID: 0}
+--- !u!196 &4
+NavMeshSettings:
+  serializedVersion: 2
+  m_ObjectHideFlags: 0
+  m_BuildSettings:
+    serializedVersion: 3
+    agentTypeID: 0
+    agentRadius: 0.5
+    agentHeight: 2
+    agentSlope: 45
+    agentClimb: 0.4
+    ledgeDropHeight: 0
+    maxJumpAcrossDistance: 0
+    minRegionArea: 2
+    manualCellSize: 0
+    cellSize: 0.16666667
+    manualTileSize: 0
+    tileSize: 256
+    buildHeightMesh: 0
+    maxJobWorkers: 0
+    preserveTilesOutsideBounds: 0
+    debug:
+      m_Flags: 0
+  m_NavMeshData: {fileID: 0}
+--- !u!1 &107963744
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 107963746}
+  - component: {fileID: 107963747}
+  m_Layer: 0
+  m_Name: RAGAndLLMSample
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &107963746
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 107963744}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &107963747
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 107963744}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fde8f7694420c760aabb639016d2d168, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  rag: {fileID: 1091532316}
+  playerText: {fileID: 1966107897}
+  AIText: {fileID: 887085510}
+  HamletText: {fileID: 4900000, guid: 145dfa55295462fa4bc804a75d8ba9c1, type: 3}
+  llmCharacter: {fileID: 498662973}
+  ParaphraseWithLLM: {fileID: 1151157495}
+--- !u!1 &158550913
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 158550917}
+  - component: {fileID: 158550916}
+  - component: {fileID: 158550915}
+  - component: {fileID: 158550914}
+  m_Layer: 5
+  m_Name: Canvas
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &158550914
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 158550913}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_IgnoreReversedGraphics: 1
+  m_BlockingObjects: 0
+  m_BlockingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+--- !u!114 &158550915
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 158550913}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_UiScaleMode: 1
+  m_ReferencePixelsPerUnit: 100
+  m_ScaleFactor: 1
+  m_ReferenceResolution: {x: 1280, y: 720}
+  m_ScreenMatchMode: 0
+  m_MatchWidthOrHeight: 0
+  m_PhysicalUnit: 3
+  m_FallbackScreenDPI: 96
+  m_DefaultSpriteDPI: 96
+  m_DynamicPixelsPerUnit: 1
+  m_PresetInfoIsWorld: 0
+--- !u!223 &158550916
+Canvas:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 158550913}
+  m_Enabled: 1
+  serializedVersion: 3
+  m_RenderMode: 0
+  m_Camera: {fileID: 0}
+  m_PlaneDistance: 100
+  m_PixelPerfect: 0
+  m_ReceivesEvents: 1
+  m_OverrideSorting: 0
+  m_OverridePixelPerfect: 0
+  m_SortingBucketNormalizedSize: 0
+  m_VertexColorAlwaysGammaSpace: 0
+  m_AdditionalShaderChannelsFlag: 0
+  m_UpdateRectTransformForStandalone: 0
+  m_SortingLayerID: 0
+  m_SortingOrder: 0
+  m_TargetDisplay: 0
+--- !u!224 &158550917
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 158550913}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 0, y: 0, z: 0}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 268891590}
+  - {fileID: 1966107896}
+  - {fileID: 2091685447}
+  - {fileID: 856480602}
+  - {fileID: 1342801405}
+  - {fileID: 724531320}
+  - {fileID: 1308766010}
+  - {fileID: 1151157496}
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 0, y: 0}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0, y: 0}
+--- !u!1 &268891589
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 268891590}
+  - component: {fileID: 268891592}
+  - component: {fileID: 268891591}
+  m_Layer: 5
+  m_Name: Panel
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &268891590
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 268891589}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1.01, y: 1.01, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &268891591
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 268891589}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0, g: 0, b: 0, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &268891592
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 268891589}
+  m_CullTransparentMesh: 1
+--- !u!1 &330318181
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 330318184}
+  - component: {fileID: 330318183}
+  - component: {fileID: 330318182}
+  m_Layer: 5
+  m_Name: Checkmark
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &330318182
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 330318181}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10901, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 0
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &330318183
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 330318181}
+  m_CullTransparentMesh: 1
+--- !u!224 &330318184
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 330318181}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 835382799}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 20, y: 20}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!1 &433287079
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 433287080}
+  - component: {fileID: 433287082}
+  - component: {fileID: 433287081}
+  m_Layer: 5
+  m_Name: Text (Legacy)
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &433287080
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 433287079}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 724531320}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &433287081
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 433287079}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0, g: 0, b: 0, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 16
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 1
+    m_MaxSize: 40
+    m_Alignment: 4
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: 'Stop
+
+'
+--- !u!222 &433287082
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 433287079}
+  m_CullTransparentMesh: 1
+--- !u!1 &498662970
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 498662972}
+  - component: {fileID: 498662973}
+  m_Layer: 0
+  m_Name: LLMCharacter
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &498662972
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 498662970}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 1024.2354, y: 495.014, z: -3.4752133}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &498662973
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 498662970}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 3f6c87a428fd5d0be9bbc686bdc8c3c2, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  advancedOptions: 0
+  remote: 0
+  _llm: {fileID: 1047848254}
+  APIKey: 
+  host: localhost
+  port: 13333
+  numRetries: 10
+  save: 
+  saveCache: 0
+  debugPrompt: 0
+  slot: -1
+  grammar: 
+  cachePrompt: 1
+  seed: 0
+  numPredict: 256
+  temperature: 0.2
+  topK: 40
+  topP: 0.9
+  minP: 0.05
+  repeatPenalty: 1.1
+  presencePenalty: 0
+  frequencyPenalty: 0
+  tfsZ: 1
+  typicalP: 1
+  repeatLastN: 64
+  penalizeNl: 1
+  penaltyPrompt: 
+  mirostat: 0
+  mirostatTau: 5
+  mirostatEta: 0.1
+  nProbs: 0
+  ignoreEos: 0
+  nKeep: -1
+  stop: []
+  stream: 1
+  playerName: Text
+  AIName: Paraphrased text
+  prompt: 'You are an assistant that answers with phrases from Hamlet.
+
+    Your
+    goal is to paraphrase the provided text without changing it too much.
+
+    Answer
+    directly with the paraphrased text.'
+  setNKeepToPrompt: 1
+  chat: []
+  grammarString: 
+--- !u!1 &718309038
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 718309039}
+  - component: {fileID: 718309041}
+  - component: {fileID: 718309040}
+  m_Layer: 5
+  m_Name: Label
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &718309039
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 718309038}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 1151157496}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 9, y: -0.5}
+  m_SizeDelta: {x: -28, y: -3}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &718309040
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 718309038}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 16
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 0
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: Paraphrase with LLM
+--- !u!222 &718309041
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 718309038}
+  m_CullTransparentMesh: 1
+--- !u!1 &724531319
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 724531320}
+  - component: {fileID: 724531323}
+  - component: {fileID: 724531322}
+  - component: {fileID: 724531321}
+  m_Layer: 5
+  m_Name: StopButton
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &724531320
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 724531319}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 433287080}
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 135.2, y: 12}
+  m_SizeDelta: {x: 107.0426, y: 30}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &724531321
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 724531319}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Navigation:
+    m_Mode: 3
+    m_WrapAround: 0
+    m_SelectOnUp: {fileID: 0}
+    m_SelectOnDown: {fileID: 0}
+    m_SelectOnLeft: {fileID: 0}
+    m_SelectOnRight: {fileID: 0}
+  m_Transition: 1
+  m_Colors:
+    m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
+    m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
+    m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
+    m_ColorMultiplier: 1
+    m_FadeDuration: 0.1
+  m_SpriteState:
+    m_HighlightedSprite: {fileID: 0}
+    m_PressedSprite: {fileID: 0}
+    m_SelectedSprite: {fileID: 0}
+    m_DisabledSprite: {fileID: 0}
+  m_AnimationTriggers:
+    m_NormalTrigger: Normal
+    m_HighlightedTrigger: Highlighted
+    m_PressedTrigger: Pressed
+    m_SelectedTrigger: Selected
+    m_DisabledTrigger: Disabled
+  m_Interactable: 1
+  m_TargetGraphic: {fileID: 724531322}
+  m_OnClick:
+    m_PersistentCalls:
+      m_Calls:
+      - m_Target: {fileID: 107963747}
+        m_TargetAssemblyTypeName: LLMUnitySamples.SimpleRAG, Assembly-CSharp
+        m_MethodName: CancelRequests
+        m_Mode: 1
+        m_Arguments:
+          m_ObjectArgument: {fileID: 0}
+          m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
+          m_IntArgument: 0
+          m_FloatArgument: 0
+          m_StringArgument: 
+          m_BoolArgument: 0
+        m_CallState: 2
+--- !u!114 &724531322
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 724531319}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.31764707, g: 0.6431373, b: 0.31764707, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &724531323
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 724531319}
+  m_CullTransparentMesh: 1
+--- !u!1 &726528676
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 726528679}
+  - component: {fileID: 726528678}
+  - component: {fileID: 726528677}
+  m_Layer: 0
+  m_Name: Main Camera
+  m_TagString: MainCamera
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!81 &726528677
+AudioListener:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 726528676}
+  m_Enabled: 1
+--- !u!20 &726528678
+Camera:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 726528676}
+  m_Enabled: 1
+  serializedVersion: 2
+  m_ClearFlags: 1
+  m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
+  m_projectionMatrixMode: 1
+  m_GateFitMode: 2
+  m_FOVAxisMode: 0
+  m_Iso: 200
+  m_ShutterSpeed: 0.005
+  m_Aperture: 16
+  m_FocusDistance: 10
+  m_FocalLength: 50
+  m_BladeCount: 5
+  m_Curvature: {x: 2, y: 11}
+  m_BarrelClipping: 0.25
+  m_Anamorphism: 0
+  m_SensorSize: {x: 36, y: 24}
+  m_LensShift: {x: 0, y: 0}
+  m_NormalizedViewPortRect:
+    serializedVersion: 2
+    x: 0
+    y: 0
+    width: 1
+    height: 1
+  near clip plane: 0.3
+  far clip plane: 1000
+  field of view: 60
+  orthographic: 0
+  orthographic size: 5
+  m_Depth: -1
+  m_CullingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+  m_RenderingPath: -1
+  m_TargetTexture: {fileID: 0}
+  m_TargetDisplay: 0
+  m_TargetEye: 3
+  m_HDR: 1
+  m_AllowMSAA: 1
+  m_AllowDynamicResolution: 0
+  m_ForceIntoRT: 0
+  m_OcclusionCulling: 1
+  m_StereoConvergence: 10
+  m_StereoSeparation: 0.022
+--- !u!4 &726528679
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 726528676}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 1, z: -10}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &835382798
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 835382799}
+  - component: {fileID: 835382800}
+  - component: {fileID: 835382801}
+  m_Layer: 5
+  m_Name: Background
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &835382799
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 835382798}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 330318184}
+  m_Father: {fileID: 1151157496}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 1}
+  m_AnchorMax: {x: 0, y: 1}
+  m_AnchoredPosition: {x: 10, y: -10}
+  m_SizeDelta: {x: 20, y: 20}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &835382800
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 835382798}
+  m_CullTransparentMesh: 1
+--- !u!114 &835382801
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 835382798}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!1 &856480601
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 856480602}
+  - component: {fileID: 856480604}
+  - component: {fileID: 856480603}
+  m_Layer: 5
+  m_Name: Player title
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &856480602
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 856480601}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 150}
+  m_SizeDelta: {x: 160, y: 30}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &856480603
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 856480601}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 20
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 2
+    m_MaxSize: 40
+    m_Alignment: 1
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: Player
+--- !u!222 &856480604
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 856480601}
+  m_CullTransparentMesh: 1
+--- !u!1 &887085508
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 887085509}
+  - component: {fileID: 887085511}
+  - component: {fileID: 887085510}
+  - component: {fileID: 887085512}
+  m_Layer: 5
+  m_Name: AIText
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &887085509
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 887085508}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 2091685447}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: -20, y: -20}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &887085510
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 887085508}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0, g: 0, b: 0, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 14
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 0
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: 
+--- !u!222 &887085511
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 887085508}
+  m_CullTransparentMesh: 1
+--- !u!210 &887085512
+SortingGroup:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 887085508}
+  m_Enabled: 1
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 1
+  m_SortAtRoot: 0
+--- !u!1 &909474451
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 909474453}
+  - component: {fileID: 909474452}
+  m_Layer: 0
+  m_Name: Directional Light
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!108 &909474452
+Light:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 909474451}
+  m_Enabled: 1
+  serializedVersion: 10
+  m_Type: 1
+  m_Shape: 0
+  m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
+  m_Intensity: 1
+  m_Range: 10
+  m_SpotAngle: 30
+  m_InnerSpotAngle: 21.80208
+  m_CookieSize: 10
+  m_Shadows:
+    m_Type: 2
+    m_Resolution: -1
+    m_CustomResolution: -1
+    m_Strength: 1
+    m_Bias: 0.05
+    m_NormalBias: 0.4
+    m_NearPlane: 0.2
+    m_CullingMatrixOverride:
+      e00: 1
+      e01: 0
+      e02: 0
+      e03: 0
+      e10: 0
+      e11: 1
+      e12: 0
+      e13: 0
+      e20: 0
+      e21: 0
+      e22: 1
+      e23: 0
+      e30: 0
+      e31: 0
+      e32: 0
+      e33: 1
+    m_UseCullingMatrixOverride: 0
+  m_Cookie: {fileID: 0}
+  m_DrawHalo: 0
+  m_Flare: {fileID: 0}
+  m_RenderMode: 0
+  m_CullingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+  m_RenderingLayerMask: 1
+  m_Lightmapping: 4
+  m_LightShadowCasterMode: 0
+  m_AreaSize: {x: 1, y: 1}
+  m_BounceIntensity: 1
+  m_ColorTemperature: 6570
+  m_UseColorTemperature: 0
+  m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
+  m_UseBoundingSphereOverride: 0
+  m_UseViewFrustumForShadowCasterCull: 1
+  m_ShadowRadius: 0
+  m_ShadowAngle: 0
+--- !u!4 &909474453
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 909474451}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
+  m_LocalPosition: {x: 0, y: 3, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
+--- !u!1 &1047848253
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1047848255}
+  - component: {fileID: 1047848254}
+  m_Layer: 0
+  m_Name: LLM
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &1047848254
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1047848253}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: a50e3140c3ecaaf1c848dbf141cc2074, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  advancedOptions: 0
+  remote: 0
+  port: 13333
+  numThreads: -1
+  numGPULayers: 0
+  debug: 0
+  parallelPrompts: -1
+  dontDestroyOnLoad: 1
+  contextSize: 8192
+  batchSize: 512
+  basePrompt: 
+  model: 
+  chatTemplate: chatml
+  lora: 
+  loraWeights: 
+  flashAttention: 0
+  APIKey: 
+  SSLCert: 
+  SSLCertPath: 
+  SSLKey: 
+  SSLKeyPath: 
+  minContextLength: 0
+  maxContextLength: 0
+  embeddingsOnly: 0
+  embeddingLength: 0
+--- !u!4 &1047848255
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1047848253}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1059033619
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1059033620}
+  - component: {fileID: 1059033622}
+  - component: {fileID: 1059033621}
+  m_Layer: 5
+  m_Name: Placeholder
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1059033620
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1059033619}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 1966107896}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: -0.5}
+  m_SizeDelta: {x: -20, y: -13}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1059033621
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1059033619}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0, g: 0, b: 0, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 16
+    m_FontStyle: 2
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 0
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: Enter text...
+--- !u!222 &1059033622
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1059033619}
+  m_CullTransparentMesh: 1
+--- !u!1 &1091532312
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1091532317}
+  - component: {fileID: 1091532316}
+  - component: {fileID: 1091532315}
+  - component: {fileID: 1091532314}
+  - component: {fileID: 1091532313}
+  m_Layer: 0
+  m_Name: RAG
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &1091532313
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1091532312}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 354c2418b0d6913efbfb73dccd540d23, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  search: {fileID: 1091532314}
+  returnChunks: 0
+  delimiters: 2e0021003a003b003f000a000d00
+--- !u!114 &1091532314
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1091532312}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: f8c6492f8c97ab9a09b0eb0f93a158da, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  llmEmbedder: {fileID: 1091532315}
+  advancedOptions: 0
+  quantization: 3
+  metricKind: 1
+  connectivity: 32
+  expansionAdd: 40
+  expansionSearch: 16
+--- !u!114 &1091532315
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1091532312}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: c6856fbefac554a38a7b8a4b353fd43d, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  advancedOptions: 0
+  remote: 0
+  _llm: {fileID: 1612143203}
+  APIKey: 
+  host: localhost
+  port: 13333
+  numRetries: 10
+--- !u!114 &1091532316
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1091532312}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: a2496546d1575771597fc8cbdd0d852d, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  searchClass: 1
+  search: {fileID: 1091532314}
+  chunkingClass: 3
+  chunking: {fileID: 1091532313}
+  preSearchClass: 0
+  preChunkingClass: 0
+--- !u!4 &1091532317
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1091532312}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 417.9513, y: 118.58295, z: -5.72276}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1151157494
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1151157496}
+  - component: {fileID: 1151157495}
+  m_Layer: 5
+  m_Name: Toggle
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &1151157495
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1151157494}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Navigation:
+    m_Mode: 3
+    m_WrapAround: 0
+    m_SelectOnUp: {fileID: 0}
+    m_SelectOnDown: {fileID: 0}
+    m_SelectOnLeft: {fileID: 0}
+    m_SelectOnRight: {fileID: 0}
+  m_Transition: 1
+  m_Colors:
+    m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
+    m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
+    m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
+    m_ColorMultiplier: 1
+    m_FadeDuration: 0.1
+  m_SpriteState:
+    m_HighlightedSprite: {fileID: 0}
+    m_PressedSprite: {fileID: 0}
+    m_SelectedSprite: {fileID: 0}
+    m_DisabledSprite: {fileID: 0}
+  m_AnimationTriggers:
+    m_NormalTrigger: Normal
+    m_HighlightedTrigger: Highlighted
+    m_PressedTrigger: Pressed
+    m_SelectedTrigger: Selected
+    m_DisabledTrigger: Disabled
+  m_Interactable: 1
+  m_TargetGraphic: {fileID: 835382801}
+  toggleTransition: 1
+  graphic: {fileID: 330318182}
+  m_Group: {fileID: 0}
+  onValueChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_IsOn: 1
+--- !u!224 &1151157496
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1151157494}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 835382799}
+  - {fileID: 718309039}
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: -98.62159, y: 8.499993}
+  m_SizeDelta: {x: 181.9969, y: 23}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!1 &1171567417
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1171567418}
+  - component: {fileID: 1171567420}
+  - component: {fileID: 1171567419}
+  m_Layer: 5
+  m_Name: Text (Legacy)
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1171567418
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1171567417}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 1308766010}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 2}
+  m_SizeDelta: {x: 25, y: 25}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1171567419
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1171567417}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 14
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 4
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: "\xD7"
+--- !u!222 &1171567420
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1171567417}
+  m_CullTransparentMesh: 1
+--- !u!1 &1308766009
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1308766010}
+  - component: {fileID: 1308766013}
+  - component: {fileID: 1308766012}
+  - component: {fileID: 1308766011}
+  m_Layer: 5
+  m_Name: ExitButton
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1308766010
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1308766009}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 1171567418}
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 1, y: 1}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 25, y: 25}
+  m_Pivot: {x: 1, y: 1}
+--- !u!114 &1308766011
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1308766009}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Navigation:
+    m_Mode: 3
+    m_WrapAround: 0
+    m_SelectOnUp: {fileID: 0}
+    m_SelectOnDown: {fileID: 0}
+    m_SelectOnLeft: {fileID: 0}
+    m_SelectOnRight: {fileID: 0}
+  m_Transition: 1
+  m_Colors:
+    m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
+    m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
+    m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
+    m_ColorMultiplier: 1
+    m_FadeDuration: 0.1
+  m_SpriteState:
+    m_HighlightedSprite: {fileID: 0}
+    m_PressedSprite: {fileID: 0}
+    m_SelectedSprite: {fileID: 0}
+    m_DisabledSprite: {fileID: 0}
+  m_AnimationTriggers:
+    m_NormalTrigger: Normal
+    m_HighlightedTrigger: Highlighted
+    m_PressedTrigger: Pressed
+    m_SelectedTrigger: Selected
+    m_DisabledTrigger: Disabled
+  m_Interactable: 1
+  m_TargetGraphic: {fileID: 1308766012}
+  m_OnClick:
+    m_PersistentCalls:
+      m_Calls:
+      - m_Target: {fileID: 107963747}
+        m_TargetAssemblyTypeName: LLMUnitySamples.SimpleRAG, Assembly-CSharp
+        m_MethodName: ExitGame
+        m_Mode: 1
+        m_Arguments:
+          m_ObjectArgument: {fileID: 0}
+          m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
+          m_IntArgument: 0
+          m_FloatArgument: 0
+          m_StringArgument: 
+          m_BoolArgument: 0
+        m_CallState: 1
+--- !u!114 &1308766012
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1308766009}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.24722636, g: 0.24722636, b: 0.24722636, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10913, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 0
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &1308766013
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1308766009}
+  m_CullTransparentMesh: 1
+--- !u!1 &1342801404
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1342801405}
+  - component: {fileID: 1342801407}
+  - component: {fileID: 1342801406}
+  m_Layer: 5
+  m_Name: AI title
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1342801405
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1342801404}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: -46}
+  m_SizeDelta: {x: 160, y: 29.6652}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1342801406
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1342801404}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 20
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 2
+    m_MaxSize: 40
+    m_Alignment: 1
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: Hamlet
+--- !u!222 &1342801407
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1342801404}
+  m_CullTransparentMesh: 1
+--- !u!1 &1609985808
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1609985809}
+  - component: {fileID: 1609985811}
+  - component: {fileID: 1609985810}
+  m_Layer: 5
+  m_Name: Text (Legacy)
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1609985809
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1609985808}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 1966107896}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: -0.5}
+  m_SizeDelta: {x: -20, y: -13}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1609985810
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1609985808}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0, g: 0, b: 0, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 14
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 0
+    m_AlignByGeometry: 0
+    m_RichText: 0
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: 
+--- !u!222 &1609985811
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1609985808}
+  m_CullTransparentMesh: 1
+--- !u!1 &1612143202
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1612143204}
+  - component: {fileID: 1612143203}
+  m_Layer: 0
+  m_Name: LLMRAG
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &1612143203
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1612143202}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: a50e3140c3ecaaf1c848dbf141cc2074, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  advancedOptions: 0
+  remote: 0
+  port: 13333
+  numThreads: -1
+  numGPULayers: 0
+  debug: 0
+  parallelPrompts: -1
+  dontDestroyOnLoad: 1
+  contextSize: 8192
+  batchSize: 512
+  basePrompt: 
+  model: 
+  chatTemplate: chatml
+  lora: 
+  loraWeights: 
+  flashAttention: 0
+  APIKey: 
+  SSLCert: 
+  SSLCertPath: 
+  SSLKey: 
+  SSLKeyPath: 
+  minContextLength: 0
+  maxContextLength: 0
+  embeddingsOnly: 0
+  embeddingLength: 0
+--- !u!4 &1612143204
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1612143202}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1966107895
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1966107896}
+  - component: {fileID: 1966107899}
+  - component: {fileID: 1966107898}
+  - component: {fileID: 1966107897}
+  m_Layer: 5
+  m_Name: PlayerInput
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1966107896
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1966107895}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 1059033620}
+  - {fileID: 1609985809}
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 87.00699}
+  m_SizeDelta: {x: 400, y: 100}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1966107897
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1966107895}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: d199490a83bb2b844b9695cbf13b01ef, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Navigation:
+    m_Mode: 3
+    m_WrapAround: 0
+    m_SelectOnUp: {fileID: 0}
+    m_SelectOnDown: {fileID: 0}
+    m_SelectOnLeft: {fileID: 0}
+    m_SelectOnRight: {fileID: 0}
+  m_Transition: 1
+  m_Colors:
+    m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
+    m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
+    m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
+    m_ColorMultiplier: 1
+    m_FadeDuration: 0.1
+  m_SpriteState:
+    m_HighlightedSprite: {fileID: 0}
+    m_PressedSprite: {fileID: 0}
+    m_SelectedSprite: {fileID: 0}
+    m_DisabledSprite: {fileID: 0}
+  m_AnimationTriggers:
+    m_NormalTrigger: Normal
+    m_HighlightedTrigger: Highlighted
+    m_PressedTrigger: Pressed
+    m_SelectedTrigger: Selected
+    m_DisabledTrigger: Disabled
+  m_Interactable: 1
+  m_TargetGraphic: {fileID: 1966107898}
+  m_TextComponent: {fileID: 1609985810}
+  m_Placeholder: {fileID: 1059033621}
+  m_ContentType: 0
+  m_InputType: 0
+  m_AsteriskChar: 42
+  m_KeyboardType: 0
+  m_LineType: 1
+  m_HideMobileInput: 0
+  m_CharacterValidation: 0
+  m_CharacterLimit: 0
+  m_OnSubmit:
+    m_PersistentCalls:
+      m_Calls: []
+  m_OnDidEndEdit:
+    m_PersistentCalls:
+      m_Calls: []
+  m_OnValueChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_CaretColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
+  m_CustomCaretColor: 0
+  m_SelectionColor: {r: 0.65882355, g: 0.80784315, b: 1, a: 0.7529412}
+  m_Text: 
+  m_CaretBlinkRate: 0.85
+  m_CaretWidth: 1
+  m_ReadOnly: 0
+  m_ShouldActivateOnSelect: 1
+--- !u!114 &1966107898
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1966107895}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.31764707, g: 0.6431373, b: 0.31764707, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &1966107899
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1966107895}
+  m_CullTransparentMesh: 1
+--- !u!1 &2015159264
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2015159267}
+  - component: {fileID: 2015159266}
+  - component: {fileID: 2015159265}
+  m_Layer: 0
+  m_Name: EventSystem
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &2015159265
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2015159264}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_SendPointerHoverToParent: 1
+  m_HorizontalAxis: Horizontal
+  m_VerticalAxis: Vertical
+  m_SubmitButton: Submit
+  m_CancelButton: Cancel
+  m_InputActionsPerSecond: 10
+  m_RepeatDelay: 0.5
+  m_ForceModuleActive: 0
+--- !u!114 &2015159266
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2015159264}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_FirstSelected: {fileID: 0}
+  m_sendNavigationEvents: 1
+  m_DragThreshold: 10
+--- !u!4 &2015159267
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2015159264}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &2091685446
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2091685447}
+  - component: {fileID: 2091685449}
+  - component: {fileID: 2091685448}
+  m_Layer: 5
+  m_Name: AIImage
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &2091685447
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2091685446}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 887085509}
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: -150}
+  m_SizeDelta: {x: 500, y: 170}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &2091685448
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2091685446}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.53662825, g: 0.53662825, b: 0.9029823, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &2091685449
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2091685446}
+  m_CullTransparentMesh: 1
+--- !u!1660057539 &9223372036854775807
+SceneRoots:
+  m_ObjectHideFlags: 0
+  m_Roots:
+  - {fileID: 726528679}
+  - {fileID: 909474453}
+  - {fileID: 158550917}
+  - {fileID: 2015159267}
+  - {fileID: 1047848255}
+  - {fileID: 1612143204}
+  - {fileID: 498662972}
+  - {fileID: 1091532317}
+  - {fileID: 107963746}
diff --git a/Samples~/RAG/RAGAndLLM_Scene.unity.meta b/Samples~/RAG/RAGAndLLM_Scene.unity.meta
new file mode 100644
index 00000000..af731aa4
--- /dev/null
+++ b/Samples~/RAG/RAGAndLLM_Scene.unity.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: a2e5c3a0f1c1b523db4bcd5e83d0e1c9
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Samples~/RAG/RAGUtils.cs b/Samples~/RAG/RAGUtils.cs
new file mode 100644
index 00000000..3afc3c0e
--- /dev/null
+++ b/Samples~/RAG/RAGUtils.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace LLMUnitySamples
+{
+    public class RAGUtils
+    {
+        public static List<string> SplitText(string text, int chunkSize = 300)
+        {
+            List<string> chunks = new List<string>();
+            int start = 0;
+            char[] delimiters = ".!;?\n\r".ToCharArray();
+
+            while (start < text.Length)
+            {
+                int end = Math.Min(start + chunkSize, text.Length);
+                if (end < text.Length)
+                {
+                    int nearestDelimiter = text.IndexOfAny(delimiters, end);
+                    if (nearestDelimiter != -1) end = nearestDelimiter + 1;
+                }
+                chunks.Add(text.Substring(start, end - start).Trim());
+                start = end;
+            }
+            return chunks;
+        }
+
+        public static Dictionary<string, List<string>> ReadGutenbergFile(string text)
+        {
+            Dictionary<string, List<string>> messages = new Dictionary<string, List<string>>();
+
+            void AddMessage(string message, string name)
+            {
+                if (name == null) return;
+                if (!messages.ContainsKey(name)) messages[name] = new List<string>();
+                messages[name].Add(message);
+            }
+
+            void AddMessages(string message, string name, string name2)
+            {
+                foreach (string chunk in SplitText(message))
+                {
+                    if (chunk == "") continue;
+                    AddMessage(chunk, name);
+                    AddMessage(chunk, name2);
+                }
+            }
+
+            // read the Hamlet play from the Gutenberg file
+            string skipPattern = @"\[.*?\]";
+            string namePattern = "^[A-Z and]+\\.$";
+            Regex nameRegex = new Regex(namePattern);
+
+            string name = null;
+            string name2 = null;
+            string message = "";
+            bool add = false;
+            int numWords = 0;
+            int numLines = 0;
+
+            string[] lines = text.Split("\n");
+            for (int i = 0; i < lines.Length; i++)
+            {
+                string line = lines[i];
+
+                if (line.Contains("***")) add = !add;
+                if (!add) continue;
+
+                line = line.Replace("\r", "");
+                line = Regex.Replace(line, skipPattern, "");
+                string lineTrim = line.Trim();
+                if (lineTrim == "" || lineTrim.StartsWith("Re-enter ") || lineTrim.StartsWith("Enter ") || lineTrim.StartsWith("SCENE")) continue;
+
+                numWords += line.Split(new[] { ' ', '\t' }, System.StringSplitOptions.RemoveEmptyEntries).Length;
+                numLines++;
+
+                if (line.StartsWith("ACT"))
+                {
+                    AddMessages(message, name, name2);
+                    name = null;
+                    name2 = null;
+                    message = "";
+                }
+                else if (nameRegex.IsMatch(line))
+                {
+                    AddMessages(message, name, name2);
+                    message = "";
+                    name = line.Replace(".", "");
+                    if (name.Contains("and"))
+                    {
+                        string[] names = name.Split(" and ");
+                        name = names[0];
+                        name2 = names[1];
+                    }
+                }
+                else if (name != null)
+                {
+                    if (message != "") message += " ";
+                    message += line;
+                }
+            }
+            return messages;
+        }
+    }
+}
diff --git a/Samples~/RAG/RAGUtils.cs.meta b/Samples~/RAG/RAGUtils.cs.meta
new file mode 100644
index 00000000..80c4be5f
--- /dev/null
+++ b/Samples~/RAG/RAGUtils.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 556ad6cc051ca686bb337db00ccc3ac2
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Samples~/RAG/RAG_Sample.cs b/Samples~/RAG/RAG_Sample.cs
new file mode 100644
index 00000000..0c1455c7
--- /dev/null
+++ b/Samples~/RAG/RAG_Sample.cs
@@ -0,0 +1,110 @@
+using System.Collections.Generic;
+using UnityEngine;
+using System.IO;
+using System.Diagnostics;
+using Debug = UnityEngine.Debug;
+using UnityEngine.UI;
+using LLMUnity;
+using System.Threading.Tasks;
+using System.Text.RegularExpressions;
+
+namespace LLMUnitySamples
+{
+    public class RAGSample : MonoBehaviour
+    {
+        public RAG rag;
+        public InputField playerText;
+        public Text AIText;
+        public TextAsset HamletText;
+        List<string> phrases;
+        string ragPath = "RAGSample.zip";
+
+        async void Start()
+        {
+            CheckLLMs(false);
+            playerText.interactable = false;
+            LoadPhrases();
+            await CreateEmbeddings();
+            playerText.onSubmit.AddListener(onInputFieldSubmit);
+            AIReplyComplete();
+        }
+
+        public void LoadPhrases()
+        {
+            phrases = RAGUtils.ReadGutenbergFile(HamletText.text)["HAMLET"];
+        }
+
+        public async Task CreateEmbeddings()
+        {
+            bool loaded = await rag.Load(ragPath);
+            if (!loaded)
+            {
+    #if UNITY_EDITOR
+                // build the embeddings
+                playerText.text += $"Creating Embeddings (only once)...\n";
+                Stopwatch stopwatch = new Stopwatch();
+                stopwatch.Start();
+                foreach (string phrase in phrases) await rag.Add(phrase);
+                stopwatch.Stop();
+                Debug.Log($"embedded {rag.Count()} phrases in {stopwatch.Elapsed.TotalMilliseconds / 1000f} secs");
+                // store the embeddings
+                rag.Save(ragPath);
+    #else
+                // if in play mode throw an error
+                throw new System.Exception("The embeddings could not be found!");
+    #endif
+            }
+        }
+
+        protected async virtual void onInputFieldSubmit(string message)
+        {
+            playerText.interactable = false;
+            AIText.text = "...";
+            (string[] similarPhrases, float[] distances) = await rag.Search(message, 1);
+            AIText.text = similarPhrases[0];
+        }
+
+        public void SetAIText(string text)
+        {
+            AIText.text = text;
+        }
+
+        public void AIReplyComplete()
+        {
+            playerText.interactable = true;
+            playerText.Select();
+            playerText.text = "";
+        }
+
+        public void ExitGame()
+        {
+            Debug.Log("Exit button clicked");
+            Application.Quit();
+        }
+
+        protected void CheckLLM(LLMCaller llmCaller, bool debug)
+        {
+            if (!llmCaller.remote && llmCaller.llm != null && llmCaller.llm.model == "")
+            {
+                string error = $"Please select a llm model in the {llmCaller.llm.gameObject.name} GameObject!";
+                if (debug) Debug.LogWarning(error);
+                else throw new System.Exception(error);
+            }
+        }
+
+        protected virtual void CheckLLMs(bool debug)
+        {
+            CheckLLM(rag.search.llmEmbedder, debug);
+        }
+
+        bool onValidateWarning = true;
+        void OnValidate()
+        {
+            if (onValidateWarning)
+            {
+                CheckLLMs(true);
+                onValidateWarning = false;
+            }
+        }
+    }
+}
diff --git a/Samples~/RAG/RAG_Sample.cs.meta b/Samples~/RAG/RAG_Sample.cs.meta
new file mode 100644
index 00000000..f2afc918
--- /dev/null
+++ b/Samples~/RAG/RAG_Sample.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a7c99e38955c9be5d9413e71ed3cab95
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Samples~/RAG/RAG_Scene.unity b/Samples~/RAG/RAG_Scene.unity
new file mode 100644
index 00000000..c1489047
--- /dev/null
+++ b/Samples~/RAG/RAG_Scene.unity
@@ -0,0 +1,1637 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!29 &1
+OcclusionCullingSettings:
+  m_ObjectHideFlags: 0
+  serializedVersion: 2
+  m_OcclusionBakeSettings:
+    smallestOccluder: 5
+    smallestHole: 0.25
+    backfaceThreshold: 100
+  m_SceneGUID: 00000000000000000000000000000000
+  m_OcclusionCullingData: {fileID: 0}
+--- !u!104 &2
+RenderSettings:
+  m_ObjectHideFlags: 0
+  serializedVersion: 9
+  m_Fog: 0
+  m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
+  m_FogMode: 3
+  m_FogDensity: 0.01
+  m_LinearFogStart: 0
+  m_LinearFogEnd: 300
+  m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
+  m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
+  m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
+  m_AmbientIntensity: 1
+  m_AmbientMode: 0
+  m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
+  m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
+  m_HaloStrength: 0.5
+  m_FlareStrength: 1
+  m_FlareFadeSpeed: 3
+  m_HaloTexture: {fileID: 0}
+  m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
+  m_DefaultReflectionMode: 0
+  m_DefaultReflectionResolution: 128
+  m_ReflectionBounces: 1
+  m_ReflectionIntensity: 1
+  m_CustomReflection: {fileID: 0}
+  m_Sun: {fileID: 0}
+  m_IndirectSpecularColor: {r: 0.44657832, g: 0.49641222, b: 0.57481664, a: 1}
+  m_UseRadianceAmbientProbe: 0
+--- !u!157 &3
+LightmapSettings:
+  m_ObjectHideFlags: 0
+  serializedVersion: 12
+  m_GIWorkflowMode: 1
+  m_GISettings:
+    serializedVersion: 2
+    m_BounceScale: 1
+    m_IndirectOutputScale: 1
+    m_AlbedoBoost: 1
+    m_EnvironmentLightingMode: 0
+    m_EnableBakedLightmaps: 1
+    m_EnableRealtimeLightmaps: 0
+  m_LightmapEditorSettings:
+    serializedVersion: 12
+    m_Resolution: 2
+    m_BakeResolution: 40
+    m_AtlasSize: 1024
+    m_AO: 0
+    m_AOMaxDistance: 1
+    m_CompAOExponent: 1
+    m_CompAOExponentDirect: 0
+    m_ExtractAmbientOcclusion: 0
+    m_Padding: 2
+    m_LightmapParameters: {fileID: 0}
+    m_LightmapsBakeMode: 1
+    m_TextureCompression: 1
+    m_FinalGather: 0
+    m_FinalGatherFiltering: 1
+    m_FinalGatherRayCount: 256
+    m_ReflectionCompression: 2
+    m_MixedBakeMode: 2
+    m_BakeBackend: 1
+    m_PVRSampling: 1
+    m_PVRDirectSampleCount: 32
+    m_PVRSampleCount: 512
+    m_PVRBounces: 2
+    m_PVREnvironmentSampleCount: 256
+    m_PVREnvironmentReferencePointCount: 2048
+    m_PVRFilteringMode: 1
+    m_PVRDenoiserTypeDirect: 1
+    m_PVRDenoiserTypeIndirect: 1
+    m_PVRDenoiserTypeAO: 1
+    m_PVRFilterTypeDirect: 0
+    m_PVRFilterTypeIndirect: 0
+    m_PVRFilterTypeAO: 0
+    m_PVREnvironmentMIS: 1
+    m_PVRCulling: 1
+    m_PVRFilteringGaussRadiusDirect: 1
+    m_PVRFilteringGaussRadiusIndirect: 5
+    m_PVRFilteringGaussRadiusAO: 2
+    m_PVRFilteringAtrousPositionSigmaDirect: 0.5
+    m_PVRFilteringAtrousPositionSigmaIndirect: 2
+    m_PVRFilteringAtrousPositionSigmaAO: 1
+    m_ExportTrainingData: 0
+    m_TrainingDataDestination: TrainingData
+    m_LightProbeSampleCountMultiplier: 4
+  m_LightingDataAsset: {fileID: 0}
+  m_LightingSettings: {fileID: 0}
+--- !u!196 &4
+NavMeshSettings:
+  serializedVersion: 2
+  m_ObjectHideFlags: 0
+  m_BuildSettings:
+    serializedVersion: 3
+    agentTypeID: 0
+    agentRadius: 0.5
+    agentHeight: 2
+    agentSlope: 45
+    agentClimb: 0.4
+    ledgeDropHeight: 0
+    maxJumpAcrossDistance: 0
+    minRegionArea: 2
+    manualCellSize: 0
+    cellSize: 0.16666667
+    manualTileSize: 0
+    tileSize: 256
+    buildHeightMesh: 0
+    maxJobWorkers: 0
+    preserveTilesOutsideBounds: 0
+    debug:
+      m_Flags: 0
+  m_NavMeshData: {fileID: 0}
+--- !u!1 &107963744
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 107963746}
+  - component: {fileID: 107963747}
+  m_Layer: 0
+  m_Name: RAGSample
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &107963746
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 107963744}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &107963747
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 107963744}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: a7c99e38955c9be5d9413e71ed3cab95, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  rag: {fileID: 1091532316}
+  playerText: {fileID: 1966107897}
+  AIText: {fileID: 887085510}
+  HamletText: {fileID: 4900000, guid: 145dfa55295462fa4bc804a75d8ba9c1, type: 3}
+--- !u!1 &158550913
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 158550917}
+  - component: {fileID: 158550916}
+  - component: {fileID: 158550915}
+  - component: {fileID: 158550914}
+  m_Layer: 5
+  m_Name: Canvas
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &158550914
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 158550913}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_IgnoreReversedGraphics: 1
+  m_BlockingObjects: 0
+  m_BlockingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+--- !u!114 &158550915
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 158550913}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_UiScaleMode: 1
+  m_ReferencePixelsPerUnit: 100
+  m_ScaleFactor: 1
+  m_ReferenceResolution: {x: 1280, y: 720}
+  m_ScreenMatchMode: 0
+  m_MatchWidthOrHeight: 0
+  m_PhysicalUnit: 3
+  m_FallbackScreenDPI: 96
+  m_DefaultSpriteDPI: 96
+  m_DynamicPixelsPerUnit: 1
+  m_PresetInfoIsWorld: 0
+--- !u!223 &158550916
+Canvas:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 158550913}
+  m_Enabled: 1
+  serializedVersion: 3
+  m_RenderMode: 0
+  m_Camera: {fileID: 0}
+  m_PlaneDistance: 100
+  m_PixelPerfect: 0
+  m_ReceivesEvents: 1
+  m_OverrideSorting: 0
+  m_OverridePixelPerfect: 0
+  m_SortingBucketNormalizedSize: 0
+  m_VertexColorAlwaysGammaSpace: 0
+  m_AdditionalShaderChannelsFlag: 0
+  m_UpdateRectTransformForStandalone: 0
+  m_SortingLayerID: 0
+  m_SortingOrder: 0
+  m_TargetDisplay: 0
+--- !u!224 &158550917
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 158550913}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 0, y: 0, z: 0}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 268891590}
+  - {fileID: 1966107896}
+  - {fileID: 2091685447}
+  - {fileID: 856480602}
+  - {fileID: 1342801405}
+  - {fileID: 1308766010}
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 0, y: 0}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0, y: 0}
+--- !u!1 &268891589
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 268891590}
+  - component: {fileID: 268891592}
+  - component: {fileID: 268891591}
+  m_Layer: 5
+  m_Name: Panel
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &268891590
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 268891589}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1.01, y: 1.01, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &268891591
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 268891589}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0, g: 0, b: 0, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &268891592
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 268891589}
+  m_CullTransparentMesh: 1
+--- !u!1 &726528676
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 726528679}
+  - component: {fileID: 726528678}
+  - component: {fileID: 726528677}
+  m_Layer: 0
+  m_Name: Main Camera
+  m_TagString: MainCamera
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!81 &726528677
+AudioListener:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 726528676}
+  m_Enabled: 1
+--- !u!20 &726528678
+Camera:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 726528676}
+  m_Enabled: 1
+  serializedVersion: 2
+  m_ClearFlags: 1
+  m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
+  m_projectionMatrixMode: 1
+  m_GateFitMode: 2
+  m_FOVAxisMode: 0
+  m_Iso: 200
+  m_ShutterSpeed: 0.005
+  m_Aperture: 16
+  m_FocusDistance: 10
+  m_FocalLength: 50
+  m_BladeCount: 5
+  m_Curvature: {x: 2, y: 11}
+  m_BarrelClipping: 0.25
+  m_Anamorphism: 0
+  m_SensorSize: {x: 36, y: 24}
+  m_LensShift: {x: 0, y: 0}
+  m_NormalizedViewPortRect:
+    serializedVersion: 2
+    x: 0
+    y: 0
+    width: 1
+    height: 1
+  near clip plane: 0.3
+  far clip plane: 1000
+  field of view: 60
+  orthographic: 0
+  orthographic size: 5
+  m_Depth: -1
+  m_CullingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+  m_RenderingPath: -1
+  m_TargetTexture: {fileID: 0}
+  m_TargetDisplay: 0
+  m_TargetEye: 3
+  m_HDR: 1
+  m_AllowMSAA: 1
+  m_AllowDynamicResolution: 0
+  m_ForceIntoRT: 0
+  m_OcclusionCulling: 1
+  m_StereoConvergence: 10
+  m_StereoSeparation: 0.022
+--- !u!4 &726528679
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 726528676}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 1, z: -10}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &856480601
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 856480602}
+  - component: {fileID: 856480604}
+  - component: {fileID: 856480603}
+  m_Layer: 5
+  m_Name: Player title
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &856480602
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 856480601}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 150}
+  m_SizeDelta: {x: 160, y: 30}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &856480603
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 856480601}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 20
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 2
+    m_MaxSize: 40
+    m_Alignment: 1
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: Player
+--- !u!222 &856480604
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 856480601}
+  m_CullTransparentMesh: 1
+--- !u!1 &887085508
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 887085509}
+  - component: {fileID: 887085511}
+  - component: {fileID: 887085510}
+  - component: {fileID: 887085512}
+  m_Layer: 5
+  m_Name: AIText
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &887085509
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 887085508}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 2091685447}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: -20, y: -20}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &887085510
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 887085508}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0, g: 0, b: 0, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 16
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 0
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: 
+--- !u!222 &887085511
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 887085508}
+  m_CullTransparentMesh: 1
+--- !u!210 &887085512
+SortingGroup:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 887085508}
+  m_Enabled: 1
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 1
+  m_SortAtRoot: 0
+--- !u!1 &909474451
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 909474453}
+  - component: {fileID: 909474452}
+  m_Layer: 0
+  m_Name: Directional Light
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!108 &909474452
+Light:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 909474451}
+  m_Enabled: 1
+  serializedVersion: 10
+  m_Type: 1
+  m_Shape: 0
+  m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
+  m_Intensity: 1
+  m_Range: 10
+  m_SpotAngle: 30
+  m_InnerSpotAngle: 21.80208
+  m_CookieSize: 10
+  m_Shadows:
+    m_Type: 2
+    m_Resolution: -1
+    m_CustomResolution: -1
+    m_Strength: 1
+    m_Bias: 0.05
+    m_NormalBias: 0.4
+    m_NearPlane: 0.2
+    m_CullingMatrixOverride:
+      e00: 1
+      e01: 0
+      e02: 0
+      e03: 0
+      e10: 0
+      e11: 1
+      e12: 0
+      e13: 0
+      e20: 0
+      e21: 0
+      e22: 1
+      e23: 0
+      e30: 0
+      e31: 0
+      e32: 0
+      e33: 1
+    m_UseCullingMatrixOverride: 0
+  m_Cookie: {fileID: 0}
+  m_DrawHalo: 0
+  m_Flare: {fileID: 0}
+  m_RenderMode: 0
+  m_CullingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+  m_RenderingLayerMask: 1
+  m_Lightmapping: 4
+  m_LightShadowCasterMode: 0
+  m_AreaSize: {x: 1, y: 1}
+  m_BounceIntensity: 1
+  m_ColorTemperature: 6570
+  m_UseColorTemperature: 0
+  m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
+  m_UseBoundingSphereOverride: 0
+  m_UseViewFrustumForShadowCasterCull: 1
+  m_ShadowRadius: 0
+  m_ShadowAngle: 0
+--- !u!4 &909474453
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 909474451}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
+  m_LocalPosition: {x: 0, y: 3, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
+--- !u!1 &1059033619
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1059033620}
+  - component: {fileID: 1059033622}
+  - component: {fileID: 1059033621}
+  m_Layer: 5
+  m_Name: Placeholder
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1059033620
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1059033619}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 1966107896}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: -0.5}
+  m_SizeDelta: {x: -20, y: -13}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1059033621
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1059033619}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0, g: 0, b: 0, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 16
+    m_FontStyle: 2
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 0
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: Enter text...
+--- !u!222 &1059033622
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1059033619}
+  m_CullTransparentMesh: 1
+--- !u!1 &1091532312
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1091532317}
+  - component: {fileID: 1091532316}
+  - component: {fileID: 1091532315}
+  - component: {fileID: 1091532314}
+  - component: {fileID: 1091532313}
+  m_Layer: 0
+  m_Name: RAG
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &1091532313
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1091532312}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 354c2418b0d6913efbfb73dccd540d23, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  search: {fileID: 1091532314}
+  returnChunks: 0
+  delimiters: 2e0021003a003b003f000a000d00
+--- !u!114 &1091532314
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1091532312}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: f8c6492f8c97ab9a09b0eb0f93a158da, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  llmEmbedder: {fileID: 1091532315}
+  advancedOptions: 0
+  quantization: 3
+  metricKind: 1
+  connectivity: 32
+  expansionAdd: 40
+  expansionSearch: 16
+--- !u!114 &1091532315
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1091532312}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: c6856fbefac554a38a7b8a4b353fd43d, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  advancedOptions: 0
+  remote: 0
+  _llm: {fileID: 1612143203}
+  APIKey: 
+  host: localhost
+  port: 13333
+  numRetries: 10
+--- !u!114 &1091532316
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1091532312}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: a2496546d1575771597fc8cbdd0d852d, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  searchClass: 1
+  search: {fileID: 1091532314}
+  chunkingClass: 3
+  chunking: {fileID: 1091532313}
+  preSearchClass: 0
+  preChunkingClass: 0
+--- !u!4 &1091532317
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1091532312}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 417.9513, y: 118.58295, z: -5.72276}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1171567417
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1171567418}
+  - component: {fileID: 1171567420}
+  - component: {fileID: 1171567419}
+  m_Layer: 5
+  m_Name: Text (Legacy)
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1171567418
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1171567417}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 1308766010}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 2}
+  m_SizeDelta: {x: 25, y: 25}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1171567419
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1171567417}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 14
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 4
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: "\xD7"
+--- !u!222 &1171567420
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1171567417}
+  m_CullTransparentMesh: 1
+--- !u!1 &1308766009
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1308766010}
+  - component: {fileID: 1308766013}
+  - component: {fileID: 1308766012}
+  - component: {fileID: 1308766011}
+  m_Layer: 5
+  m_Name: ExitButton
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1308766010
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1308766009}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 1171567418}
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 1, y: 1}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 25, y: 25}
+  m_Pivot: {x: 1, y: 1}
+--- !u!114 &1308766011
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1308766009}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Navigation:
+    m_Mode: 3
+    m_WrapAround: 0
+    m_SelectOnUp: {fileID: 0}
+    m_SelectOnDown: {fileID: 0}
+    m_SelectOnLeft: {fileID: 0}
+    m_SelectOnRight: {fileID: 0}
+  m_Transition: 1
+  m_Colors:
+    m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
+    m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
+    m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
+    m_ColorMultiplier: 1
+    m_FadeDuration: 0.1
+  m_SpriteState:
+    m_HighlightedSprite: {fileID: 0}
+    m_PressedSprite: {fileID: 0}
+    m_SelectedSprite: {fileID: 0}
+    m_DisabledSprite: {fileID: 0}
+  m_AnimationTriggers:
+    m_NormalTrigger: Normal
+    m_HighlightedTrigger: Highlighted
+    m_PressedTrigger: Pressed
+    m_SelectedTrigger: Selected
+    m_DisabledTrigger: Disabled
+  m_Interactable: 1
+  m_TargetGraphic: {fileID: 1308766012}
+  m_OnClick:
+    m_PersistentCalls:
+      m_Calls:
+      - m_Target: {fileID: 0}
+        m_TargetAssemblyTypeName: LLMUnitySamples.RAGSample, Assembly-CSharp
+        m_MethodName: ExitGame
+        m_Mode: 1
+        m_Arguments:
+          m_ObjectArgument: {fileID: 0}
+          m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
+          m_IntArgument: 0
+          m_FloatArgument: 0
+          m_StringArgument: 
+          m_BoolArgument: 0
+        m_CallState: 1
+--- !u!114 &1308766012
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1308766009}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.24722636, g: 0.24722636, b: 0.24722636, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10913, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 0
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &1308766013
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1308766009}
+  m_CullTransparentMesh: 1
+--- !u!1 &1342801404
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1342801405}
+  - component: {fileID: 1342801407}
+  - component: {fileID: 1342801406}
+  m_Layer: 5
+  m_Name: AI title
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1342801405
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1342801404}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: -46}
+  m_SizeDelta: {x: 160, y: 29.6652}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1342801406
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1342801404}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 20
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 2
+    m_MaxSize: 40
+    m_Alignment: 1
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: Hamlet
+--- !u!222 &1342801407
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1342801404}
+  m_CullTransparentMesh: 1
+--- !u!1 &1609985808
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1609985809}
+  - component: {fileID: 1609985811}
+  - component: {fileID: 1609985810}
+  m_Layer: 5
+  m_Name: Text (Legacy)
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1609985809
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1609985808}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 1966107896}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: -0.5}
+  m_SizeDelta: {x: -20, y: -13}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1609985810
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1609985808}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0, g: 0, b: 0, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 16
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 0
+    m_AlignByGeometry: 0
+    m_RichText: 0
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: 
+--- !u!222 &1609985811
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1609985808}
+  m_CullTransparentMesh: 1
+--- !u!1 &1612143202
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1612143204}
+  - component: {fileID: 1612143203}
+  m_Layer: 0
+  m_Name: LLMRAG
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &1612143203
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1612143202}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: a50e3140c3ecaaf1c848dbf141cc2074, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  advancedOptions: 0
+  remote: 0
+  port: 13333
+  numThreads: -1
+  numGPULayers: 0
+  debug: 0
+  parallelPrompts: -1
+  dontDestroyOnLoad: 1
+  contextSize: 8192
+  batchSize: 512
+  basePrompt: 
+  model: 
+  chatTemplate: chatml
+  lora: 
+  loraWeights: 
+  flashAttention: 0
+  APIKey: 
+  SSLCert: 
+  SSLCertPath: 
+  SSLKey: 
+  SSLKeyPath: 
+  minContextLength: 0
+  maxContextLength: 0
+  embeddingsOnly: 0
+  embeddingLength: 0
+--- !u!4 &1612143204
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1612143202}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1966107895
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1966107896}
+  - component: {fileID: 1966107899}
+  - component: {fileID: 1966107898}
+  - component: {fileID: 1966107897}
+  m_Layer: 5
+  m_Name: PlayerInput
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1966107896
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1966107895}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 1059033620}
+  - {fileID: 1609985809}
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 87.00699}
+  m_SizeDelta: {x: 400, y: 100}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1966107897
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1966107895}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: d199490a83bb2b844b9695cbf13b01ef, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Navigation:
+    m_Mode: 3
+    m_WrapAround: 0
+    m_SelectOnUp: {fileID: 0}
+    m_SelectOnDown: {fileID: 0}
+    m_SelectOnLeft: {fileID: 0}
+    m_SelectOnRight: {fileID: 0}
+  m_Transition: 1
+  m_Colors:
+    m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
+    m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
+    m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
+    m_ColorMultiplier: 1
+    m_FadeDuration: 0.1
+  m_SpriteState:
+    m_HighlightedSprite: {fileID: 0}
+    m_PressedSprite: {fileID: 0}
+    m_SelectedSprite: {fileID: 0}
+    m_DisabledSprite: {fileID: 0}
+  m_AnimationTriggers:
+    m_NormalTrigger: Normal
+    m_HighlightedTrigger: Highlighted
+    m_PressedTrigger: Pressed
+    m_SelectedTrigger: Selected
+    m_DisabledTrigger: Disabled
+  m_Interactable: 1
+  m_TargetGraphic: {fileID: 1966107898}
+  m_TextComponent: {fileID: 1609985810}
+  m_Placeholder: {fileID: 1059033621}
+  m_ContentType: 0
+  m_InputType: 0
+  m_AsteriskChar: 42
+  m_KeyboardType: 0
+  m_LineType: 1
+  m_HideMobileInput: 0
+  m_CharacterValidation: 0
+  m_CharacterLimit: 0
+  m_OnSubmit:
+    m_PersistentCalls:
+      m_Calls: []
+  m_OnDidEndEdit:
+    m_PersistentCalls:
+      m_Calls: []
+  m_OnValueChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_CaretColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
+  m_CustomCaretColor: 0
+  m_SelectionColor: {r: 0.65882355, g: 0.80784315, b: 1, a: 0.7529412}
+  m_Text: 
+  m_CaretBlinkRate: 0.85
+  m_CaretWidth: 1
+  m_ReadOnly: 0
+  m_ShouldActivateOnSelect: 1
+--- !u!114 &1966107898
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1966107895}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.31764707, g: 0.6431373, b: 0.31764707, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &1966107899
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1966107895}
+  m_CullTransparentMesh: 1
+--- !u!1 &2015159264
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2015159267}
+  - component: {fileID: 2015159266}
+  - component: {fileID: 2015159265}
+  m_Layer: 0
+  m_Name: EventSystem
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &2015159265
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2015159264}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_SendPointerHoverToParent: 1
+  m_HorizontalAxis: Horizontal
+  m_VerticalAxis: Vertical
+  m_SubmitButton: Submit
+  m_CancelButton: Cancel
+  m_InputActionsPerSecond: 10
+  m_RepeatDelay: 0.5
+  m_ForceModuleActive: 0
+--- !u!114 &2015159266
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2015159264}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_FirstSelected: {fileID: 0}
+  m_sendNavigationEvents: 1
+  m_DragThreshold: 10
+--- !u!4 &2015159267
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2015159264}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &2091685446
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2091685447}
+  - component: {fileID: 2091685449}
+  - component: {fileID: 2091685448}
+  m_Layer: 5
+  m_Name: AIImage
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &2091685447
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2091685446}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 887085509}
+  m_Father: {fileID: 158550917}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: -150}
+  m_SizeDelta: {x: 500, y: 170}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &2091685448
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2091685446}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.53662825, g: 0.53662825, b: 0.9029823, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &2091685449
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2091685446}
+  m_CullTransparentMesh: 1
+--- !u!1660057539 &9223372036854775807
+SceneRoots:
+  m_ObjectHideFlags: 0
+  m_Roots:
+  - {fileID: 726528679}
+  - {fileID: 909474453}
+  - {fileID: 158550917}
+  - {fileID: 2015159267}
+  - {fileID: 1612143204}
+  - {fileID: 1091532317}
+  - {fileID: 107963746}
diff --git a/Samples~/RAG/RAG_Scene.unity.meta b/Samples~/RAG/RAG_Scene.unity.meta
new file mode 100644
index 00000000..6d6769bb
--- /dev/null
+++ b/Samples~/RAG/RAG_Scene.unity.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 4ee0034669d1095f99f880a6b08c69a4
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Samples~/RAG/hamlet_project_gutenberg.txt b/Samples~/RAG/hamlet_project_gutenberg.txt
new file mode 100644
index 00000000..e9d06d7e
--- /dev/null
+++ b/Samples~/RAG/hamlet_project_gutenberg.txt
@@ -0,0 +1,7085 @@
+The Project Gutenberg eBook of Hamlet, Prince of Denmark
+    
+This ebook is for the use of anyone anywhere in the United States and
+most other parts of the world at no cost and with almost no restrictions
+whatsoever. You may copy it, give it away or re-use it under the terms
+of the Project Gutenberg License included with this ebook or online
+at www.gutenberg.org. If you are not located in the United States,
+you will have to check the laws of the country where you are located
+before using this eBook.
+
+Title: Hamlet, Prince of Denmark
+
+
+Author: William Shakespeare
+
+Release date: November 1, 1998 [eBook #1524]
+                Most recently updated: November 11, 2023
+
+Language: English
+
+
+
+*** START OF THE PROJECT GUTENBERG EBOOK HAMLET, PRINCE OF DENMARK ***
+
+
+
+
+cover
+
+
+
+
+THE TRAGEDY OF HAMLET, PRINCE OF DENMARK
+
+by William Shakespeare
+
+
+
+
+Contents
+
+ ACT I
+ Scene I. Elsinore. A platform before the Castle
+ Scene II. Elsinore. A room of state in the Castle
+ Scene III. A room in Polonius’s house
+ Scene IV. The platform
+ Scene V. A more remote part of the Castle
+
+ ACT II
+ Scene I. A room in Polonius’s house
+ Scene II. A room in the Castle
+
+ ACT III
+ Scene I. A room in the Castle
+ Scene II. A hall in the Castle
+ Scene III. A room in the Castle
+ Scene IV. Another room in the Castle
+
+ ACT IV
+ Scene I. A room in the Castle
+ Scene II. Another room in the Castle
+ Scene III. Another room in the Castle
+ Scene IV. A plain in Denmark
+ Scene V. Elsinore. A room in the Castle
+ Scene VI. Another room in the Castle
+ Scene VII. Another room in the Castle
+
+ ACT V
+ Scene I. A churchyard
+ Scene II. A hall in the Castle
+
+
+
+
+Dramatis Personæ
+
+HAMLET, Prince of Denmark
+CLAUDIUS, King of Denmark, Hamlet’s uncle
+The GHOST of the late king, Hamlet’s father
+GERTRUDE, the Queen, Hamlet’s mother, now wife of Claudius
+POLONIUS, Lord Chamberlain
+LAERTES, Son to Polonius
+OPHELIA, Daughter to Polonius
+HORATIO, Friend to Hamlet
+FORTINBRAS, Prince of Norway
+VOLTEMAND, Courtier
+CORNELIUS, Courtier
+ROSENCRANTZ, Courtier
+GUILDENSTERN, Courtier
+MARCELLUS, Officer
+BARNARDO, Officer
+FRANCISCO, a Soldier
+OSRIC, Courtier
+REYNALDO, Servant to Polonius
+Players
+A Gentleman, Courtier
+A Priest
+Two Clowns, Grave-diggers
+A Captain
+English Ambassadors.
+Lords, Ladies, Officers, Soldiers, Sailors, Messengers, and Attendants
+
+SCENE. Elsinore.
+
+
+
+
+ACT I
+
+SCENE I. Elsinore. A platform before the Castle.
+
+
+Enter Francisco and Barnardo, two sentinels.
+
+BARNARDO.
+Who’s there?
+
+FRANCISCO.
+Nay, answer me. Stand and unfold yourself.
+
+BARNARDO.
+Long live the King!
+
+FRANCISCO.
+Barnardo?
+
+BARNARDO.
+He.
+
+FRANCISCO.
+You come most carefully upon your hour.
+
+BARNARDO.
+’Tis now struck twelve. Get thee to bed, Francisco.
+
+FRANCISCO.
+For this relief much thanks. ’Tis bitter cold,
+And I am sick at heart.
+
+BARNARDO.
+Have you had quiet guard?
+
+FRANCISCO.
+Not a mouse stirring.
+
+BARNARDO.
+Well, good night.
+If you do meet Horatio and Marcellus,
+The rivals of my watch, bid them make haste.
+
+Enter Horatio and Marcellus.
+
+FRANCISCO.
+I think I hear them. Stand, ho! Who is there?
+
+HORATIO.
+Friends to this ground.
+
+MARCELLUS.
+And liegemen to the Dane.
+
+FRANCISCO.
+Give you good night.
+
+MARCELLUS.
+O, farewell, honest soldier, who hath reliev’d you?
+
+FRANCISCO.
+Barnardo has my place. Give you good-night.
+
+[_Exit._]
+
+MARCELLUS.
+Holla, Barnardo!
+
+BARNARDO.
+Say, what, is Horatio there?
+
+HORATIO.
+A piece of him.
+
+BARNARDO.
+Welcome, Horatio. Welcome, good Marcellus.
+
+MARCELLUS.
+What, has this thing appear’d again tonight?
+
+BARNARDO.
+I have seen nothing.
+
+MARCELLUS.
+Horatio says ’tis but our fantasy,
+And will not let belief take hold of him
+Touching this dreaded sight, twice seen of us.
+Therefore I have entreated him along
+With us to watch the minutes of this night,
+That if again this apparition come
+He may approve our eyes and speak to it.
+
+HORATIO.
+Tush, tush, ’twill not appear.
+
+BARNARDO.
+Sit down awhile,
+And let us once again assail your ears,
+That are so fortified against our story,
+What we two nights have seen.
+
+HORATIO.
+Well, sit we down,
+And let us hear Barnardo speak of this.
+
+BARNARDO.
+Last night of all,
+When yond same star that’s westward from the pole,
+Had made his course t’illume that part of heaven
+Where now it burns, Marcellus and myself,
+The bell then beating one—
+
+MARCELLUS.
+Peace, break thee off. Look where it comes again.
+
+Enter Ghost.
+
+BARNARDO.
+In the same figure, like the King that’s dead.
+
+MARCELLUS.
+Thou art a scholar; speak to it, Horatio.
+
+BARNARDO.
+Looks it not like the King? Mark it, Horatio.
+
+HORATIO.
+Most like. It harrows me with fear and wonder.
+
+BARNARDO
+It would be spoke to.
+
+MARCELLUS.
+Question it, Horatio.
+
+HORATIO.
+What art thou that usurp’st this time of night,
+Together with that fair and warlike form
+In which the majesty of buried Denmark
+Did sometimes march? By heaven I charge thee speak.
+
+MARCELLUS.
+It is offended.
+
+BARNARDO.
+See, it stalks away.
+
+HORATIO.
+Stay! speak, speak! I charge thee speak!
+
+[_Exit Ghost._]
+
+MARCELLUS.
+’Tis gone, and will not answer.
+
+BARNARDO.
+How now, Horatio! You tremble and look pale.
+Is not this something more than fantasy?
+What think you on’t?
+
+HORATIO.
+Before my God, I might not this believe
+Without the sensible and true avouch
+Of mine own eyes.
+
+MARCELLUS.
+Is it not like the King?
+
+HORATIO.
+As thou art to thyself:
+Such was the very armour he had on
+When he th’ambitious Norway combated;
+So frown’d he once, when in an angry parle
+He smote the sledded Polacks on the ice.
+’Tis strange.
+
+MARCELLUS.
+Thus twice before, and jump at this dead hour,
+With martial stalk hath he gone by our watch.
+
+HORATIO.
+In what particular thought to work I know not;
+But in the gross and scope of my opinion,
+This bodes some strange eruption to our state.
+
+MARCELLUS.
+Good now, sit down, and tell me, he that knows,
+Why this same strict and most observant watch
+So nightly toils the subject of the land,
+And why such daily cast of brazen cannon
+And foreign mart for implements of war;
+Why such impress of shipwrights, whose sore task
+Does not divide the Sunday from the week.
+What might be toward, that this sweaty haste
+Doth make the night joint-labourer with the day:
+Who is’t that can inform me?
+
+HORATIO.
+That can I;
+At least, the whisper goes so. Our last King,
+Whose image even but now appear’d to us,
+Was, as you know, by Fortinbras of Norway,
+Thereto prick’d on by a most emulate pride,
+Dar’d to the combat; in which our valiant Hamlet,
+For so this side of our known world esteem’d him,
+Did slay this Fortinbras; who by a seal’d compact,
+Well ratified by law and heraldry,
+Did forfeit, with his life, all those his lands
+Which he stood seiz’d of, to the conqueror;
+Against the which, a moiety competent
+Was gaged by our King; which had return’d
+To the inheritance of Fortinbras,
+Had he been vanquisher; as by the same cov’nant
+And carriage of the article design’d,
+His fell to Hamlet. Now, sir, young Fortinbras,
+Of unimproved mettle, hot and full,
+Hath in the skirts of Norway, here and there,
+Shark’d up a list of lawless resolutes,
+For food and diet, to some enterprise
+That hath a stomach in’t; which is no other,
+As it doth well appear unto our state,
+But to recover of us by strong hand
+And terms compulsatory, those foresaid lands
+So by his father lost. And this, I take it,
+Is the main motive of our preparations,
+The source of this our watch, and the chief head
+Of this post-haste and rummage in the land.
+
+BARNARDO.
+I think it be no other but e’en so:
+Well may it sort that this portentous figure
+Comes armed through our watch so like the King
+That was and is the question of these wars.
+
+HORATIO.
+A mote it is to trouble the mind’s eye.
+In the most high and palmy state of Rome,
+A little ere the mightiest Julius fell,
+The graves stood tenantless and the sheeted dead
+Did squeak and gibber in the Roman streets;
+As stars with trains of fire and dews of blood,
+Disasters in the sun; and the moist star,
+Upon whose influence Neptune’s empire stands,
+Was sick almost to doomsday with eclipse.
+And even the like precurse of fierce events,
+As harbingers preceding still the fates
+And prologue to the omen coming on,
+Have heaven and earth together demonstrated
+Unto our climatures and countrymen.
+
+Re-enter Ghost.
+
+But, soft, behold! Lo, where it comes again!
+I’ll cross it, though it blast me. Stay, illusion!
+If thou hast any sound, or use of voice,
+Speak to me.
+If there be any good thing to be done,
+That may to thee do ease, and grace to me,
+Speak to me.
+If thou art privy to thy country’s fate,
+Which, happily, foreknowing may avoid,
+O speak!
+Or if thou hast uphoarded in thy life
+Extorted treasure in the womb of earth,
+For which, they say, you spirits oft walk in death,
+Speak of it. Stay, and speak!
+
+[_The cock crows._]
+
+Stop it, Marcellus!
+
+MARCELLUS.
+Shall I strike at it with my partisan?
+
+HORATIO.
+Do, if it will not stand.
+
+BARNARDO.
+’Tis here!
+
+HORATIO.
+’Tis here!
+
+[_Exit Ghost._]
+
+MARCELLUS.
+’Tis gone!
+We do it wrong, being so majestical,
+To offer it the show of violence,
+For it is as the air, invulnerable,
+And our vain blows malicious mockery.
+
+BARNARDO.
+It was about to speak, when the cock crew.
+
+HORATIO.
+And then it started, like a guilty thing
+Upon a fearful summons. I have heard
+The cock, that is the trumpet to the morn,
+Doth with his lofty and shrill-sounding throat
+Awake the god of day; and at his warning,
+Whether in sea or fire, in earth or air,
+Th’extravagant and erring spirit hies
+To his confine. And of the truth herein
+This present object made probation.
+
+MARCELLUS.
+It faded on the crowing of the cock.
+Some say that ever ’gainst that season comes
+Wherein our Saviour’s birth is celebrated,
+The bird of dawning singeth all night long;
+And then, they say, no spirit dare stir abroad,
+The nights are wholesome, then no planets strike,
+No fairy takes, nor witch hath power to charm;
+So hallow’d and so gracious is the time.
+
+HORATIO.
+So have I heard, and do in part believe it.
+But look, the morn in russet mantle clad,
+Walks o’er the dew of yon high eastward hill.
+Break we our watch up, and by my advice,
+Let us impart what we have seen tonight
+Unto young Hamlet; for upon my life,
+This spirit, dumb to us, will speak to him.
+Do you consent we shall acquaint him with it,
+As needful in our loves, fitting our duty?
+
+MARCELLUS.
+Let’s do’t, I pray, and I this morning know
+Where we shall find him most conveniently.
+
+[_Exeunt._]
+
+ SCENE II. Elsinore. A room of state in the Castle.
+
+Enter Claudius King of Denmark, Gertrude the Queen, Hamlet, Polonius,
+Laertes, Voltemand,
+Cornelius, Lords and Attendant.
+
+KING.
+Though yet of Hamlet our dear brother’s death
+The memory be green, and that it us befitted
+To bear our hearts in grief, and our whole kingdom
+To be contracted in one brow of woe;
+Yet so far hath discretion fought with nature
+That we with wisest sorrow think on him,
+Together with remembrance of ourselves.
+Therefore our sometime sister, now our queen,
+Th’imperial jointress to this warlike state,
+Have we, as ’twere with a defeated joy,
+With one auspicious and one dropping eye,
+With mirth in funeral, and with dirge in marriage,
+In equal scale weighing delight and dole,
+Taken to wife; nor have we herein barr’d
+Your better wisdoms, which have freely gone
+With this affair along. For all, our thanks.
+Now follows, that you know young Fortinbras,
+Holding a weak supposal of our worth,
+Or thinking by our late dear brother’s death
+Our state to be disjoint and out of frame,
+Colleagued with this dream of his advantage,
+He hath not fail’d to pester us with message,
+Importing the surrender of those lands
+Lost by his father, with all bonds of law,
+To our most valiant brother. So much for him.
+Now for ourself and for this time of meeting:
+Thus much the business is: we have here writ
+To Norway, uncle of young Fortinbras,
+Who, impotent and bed-rid, scarcely hears
+Of this his nephew’s purpose, to suppress
+His further gait herein; in that the levies,
+The lists, and full proportions are all made
+Out of his subject: and we here dispatch
+You, good Cornelius, and you, Voltemand,
+For bearers of this greeting to old Norway,
+Giving to you no further personal power
+To business with the King, more than the scope
+Of these dilated articles allow.
+Farewell; and let your haste commend your duty.
+
+CORNELIUS and VOLTEMAND.
+In that, and all things, will we show our duty.
+
+KING.
+We doubt it nothing: heartily farewell.
+
+[_Exeunt Voltemand and Cornelius._]
+
+And now, Laertes, what’s the news with you?
+You told us of some suit. What is’t, Laertes?
+You cannot speak of reason to the Dane,
+And lose your voice. What wouldst thou beg, Laertes,
+That shall not be my offer, not thy asking?
+The head is not more native to the heart,
+The hand more instrumental to the mouth,
+Than is the throne of Denmark to thy father.
+What wouldst thou have, Laertes?
+
+LAERTES.
+Dread my lord,
+Your leave and favour to return to France,
+From whence though willingly I came to Denmark
+To show my duty in your coronation;
+Yet now I must confess, that duty done,
+My thoughts and wishes bend again toward France,
+And bow them to your gracious leave and pardon.
+
+KING.
+Have you your father’s leave? What says Polonius?
+
+POLONIUS.
+He hath, my lord, wrung from me my slow leave
+By laboursome petition; and at last
+Upon his will I seal’d my hard consent.
+I do beseech you give him leave to go.
+
+KING.
+Take thy fair hour, Laertes; time be thine,
+And thy best graces spend it at thy will!
+But now, my cousin Hamlet, and my son—
+
+HAMLET.
+[_Aside._] A little more than kin, and less than kind.
+
+KING.
+How is it that the clouds still hang on you?
+
+HAMLET.
+Not so, my lord, I am too much i’ the sun.
+
+QUEEN.
+Good Hamlet, cast thy nighted colour off,
+And let thine eye look like a friend on Denmark.
+Do not for ever with thy vailed lids
+Seek for thy noble father in the dust.
+Thou know’st ’tis common, all that lives must die,
+Passing through nature to eternity.
+
+HAMLET.
+Ay, madam, it is common.
+
+QUEEN.
+If it be,
+Why seems it so particular with thee?
+
+HAMLET.
+Seems, madam! Nay, it is; I know not seems.
+’Tis not alone my inky cloak, good mother,
+Nor customary suits of solemn black,
+Nor windy suspiration of forc’d breath,
+No, nor the fruitful river in the eye,
+Nor the dejected haviour of the visage,
+Together with all forms, moods, shows of grief,
+That can denote me truly. These indeed seem,
+For they are actions that a man might play;
+But I have that within which passeth show;
+These but the trappings and the suits of woe.
+
+KING.
+’Tis sweet and commendable in your nature, Hamlet,
+To give these mourning duties to your father;
+But you must know, your father lost a father,
+That father lost, lost his, and the survivor bound
+In filial obligation, for some term
+To do obsequious sorrow. But to persevere
+In obstinate condolement is a course
+Of impious stubbornness. ’Tis unmanly grief,
+It shows a will most incorrect to heaven,
+A heart unfortified, a mind impatient,
+An understanding simple and unschool’d;
+For what we know must be, and is as common
+As any the most vulgar thing to sense,
+Why should we in our peevish opposition
+Take it to heart? Fie, ’tis a fault to heaven,
+A fault against the dead, a fault to nature,
+To reason most absurd, whose common theme
+Is death of fathers, and who still hath cried,
+From the first corse till he that died today,
+‘This must be so.’ We pray you throw to earth
+This unprevailing woe, and think of us
+As of a father; for let the world take note
+You are the most immediate to our throne,
+And with no less nobility of love
+Than that which dearest father bears his son
+Do I impart toward you. For your intent
+In going back to school in Wittenberg,
+It is most retrograde to our desire:
+And we beseech you bend you to remain
+Here in the cheer and comfort of our eye,
+Our chiefest courtier, cousin, and our son.
+
+QUEEN.
+Let not thy mother lose her prayers, Hamlet.
+I pray thee stay with us; go not to Wittenberg.
+
+HAMLET.
+I shall in all my best obey you, madam.
+
+KING.
+Why, ’tis a loving and a fair reply.
+Be as ourself in Denmark. Madam, come;
+This gentle and unforc’d accord of Hamlet
+Sits smiling to my heart; in grace whereof,
+No jocund health that Denmark drinks today
+But the great cannon to the clouds shall tell,
+And the King’s rouse the heaven shall bruit again,
+Re-speaking earthly thunder. Come away.
+
+[_Exeunt all but Hamlet._]
+
+HAMLET.
+O that this too too solid flesh would melt,
+Thaw, and resolve itself into a dew!
+Or that the Everlasting had not fix’d
+His canon ’gainst self-slaughter. O God! O God!
+How weary, stale, flat, and unprofitable
+Seem to me all the uses of this world!
+Fie on’t! Oh fie! ’tis an unweeded garden
+That grows to seed; things rank and gross in nature
+Possess it merely. That it should come to this!
+But two months dead—nay, not so much, not two:
+So excellent a king; that was to this
+Hyperion to a satyr; so loving to my mother,
+That he might not beteem the winds of heaven
+Visit her face too roughly. Heaven and earth!
+Must I remember? Why, she would hang on him
+As if increase of appetite had grown
+By what it fed on; and yet, within a month—
+Let me not think on’t—Frailty, thy name is woman!
+A little month, or ere those shoes were old
+With which she followed my poor father’s body
+Like Niobe, all tears.—Why she, even she—
+O God! A beast that wants discourse of reason
+Would have mourn’d longer,—married with mine uncle,
+My father’s brother; but no more like my father
+Than I to Hercules. Within a month,
+Ere yet the salt of most unrighteous tears
+Had left the flushing in her galled eyes,
+She married. O most wicked speed, to post
+With such dexterity to incestuous sheets!
+It is not, nor it cannot come to good.
+But break, my heart, for I must hold my tongue.
+
+Enter Horatio, Marcellus and Barnardo.
+
+HORATIO.
+Hail to your lordship!
+
+HAMLET.
+I am glad to see you well:
+Horatio, or I do forget myself.
+
+HORATIO.
+The same, my lord,
+And your poor servant ever.
+
+HAMLET.
+Sir, my good friend;
+I’ll change that name with you:
+And what make you from Wittenberg, Horatio?—
+Marcellus?
+
+MARCELLUS.
+My good lord.
+
+HAMLET.
+I am very glad to see you.—Good even, sir.—
+But what, in faith, make you from Wittenberg?
+
+HORATIO.
+A truant disposition, good my lord.
+
+HAMLET.
+I would not hear your enemy say so;
+Nor shall you do my ear that violence,
+To make it truster of your own report
+Against yourself. I know you are no truant.
+But what is your affair in Elsinore?
+We’ll teach you to drink deep ere you depart.
+
+HORATIO.
+My lord, I came to see your father’s funeral.
+
+HAMLET.
+I prithee do not mock me, fellow-student.
+I think it was to see my mother’s wedding.
+
+HORATIO.
+Indeed, my lord, it follow’d hard upon.
+
+HAMLET.
+Thrift, thrift, Horatio! The funeral bak’d meats
+Did coldly furnish forth the marriage tables.
+Would I had met my dearest foe in heaven
+Or ever I had seen that day, Horatio.
+My father,—methinks I see my father.
+
+HORATIO.
+Where, my lord?
+
+HAMLET.
+In my mind’s eye, Horatio.
+
+HORATIO.
+I saw him once; he was a goodly king.
+
+HAMLET.
+He was a man, take him for all in all,
+I shall not look upon his like again.
+
+HORATIO.
+My lord, I think I saw him yesternight.
+
+HAMLET.
+Saw? Who?
+
+HORATIO.
+My lord, the King your father.
+
+HAMLET.
+The King my father!
+
+HORATIO.
+Season your admiration for a while
+With an attent ear, till I may deliver
+Upon the witness of these gentlemen
+This marvel to you.
+
+HAMLET.
+For God’s love let me hear.
+
+HORATIO.
+Two nights together had these gentlemen,
+Marcellus and Barnardo, on their watch
+In the dead waste and middle of the night,
+Been thus encounter’d. A figure like your father,
+Armed at point exactly, cap-à-pie,
+Appears before them, and with solemn march
+Goes slow and stately by them: thrice he walk’d
+By their oppress’d and fear-surprised eyes,
+Within his truncheon’s length; whilst they, distill’d
+Almost to jelly with the act of fear,
+Stand dumb, and speak not to him. This to me
+In dreadful secrecy impart they did,
+And I with them the third night kept the watch,
+Where, as they had deliver’d, both in time,
+Form of the thing, each word made true and good,
+The apparition comes. I knew your father;
+These hands are not more like.
+
+HAMLET.
+But where was this?
+
+MARCELLUS.
+My lord, upon the platform where we watch.
+
+HAMLET.
+Did you not speak to it?
+
+HORATIO.
+My lord, I did;
+But answer made it none: yet once methought
+It lifted up it head, and did address
+Itself to motion, like as it would speak.
+But even then the morning cock crew loud,
+And at the sound it shrunk in haste away,
+And vanish’d from our sight.
+
+HAMLET.
+’Tis very strange.
+
+HORATIO.
+As I do live, my honour’d lord, ’tis true;
+And we did think it writ down in our duty
+To let you know of it.
+
+HAMLET.
+Indeed, indeed, sirs, but this troubles me.
+Hold you the watch tonight?
+
+MARCELLUS and BARNARDO.
+We do, my lord.
+
+HAMLET.
+Arm’d, say you?
+
+Both.
+Arm’d, my lord.
+
+HAMLET.
+From top to toe?
+
+BOTH.
+My lord, from head to foot.
+
+HAMLET.
+Then saw you not his face?
+
+HORATIO.
+O yes, my lord, he wore his beaver up.
+
+HAMLET.
+What, look’d he frowningly?
+
+HORATIO.
+A countenance more in sorrow than in anger.
+
+HAMLET.
+Pale, or red?
+
+HORATIO.
+Nay, very pale.
+
+HAMLET.
+And fix’d his eyes upon you?
+
+HORATIO.
+Most constantly.
+
+HAMLET.
+I would I had been there.
+
+HORATIO.
+It would have much amaz’d you.
+
+HAMLET.
+Very like, very like. Stay’d it long?
+
+HORATIO.
+While one with moderate haste might tell a hundred.
+
+MARCELLUS and BARNARDO.
+Longer, longer.
+
+HORATIO.
+Not when I saw’t.
+
+HAMLET.
+His beard was grizzled, no?
+
+HORATIO.
+It was, as I have seen it in his life,
+A sable silver’d.
+
+HAMLET.
+I will watch tonight;
+Perchance ’twill walk again.
+
+HORATIO.
+I warrant you it will.
+
+HAMLET.
+If it assume my noble father’s person,
+I’ll speak to it, though hell itself should gape
+And bid me hold my peace. I pray you all,
+If you have hitherto conceal’d this sight,
+Let it be tenable in your silence still;
+And whatsoever else shall hap tonight,
+Give it an understanding, but no tongue.
+I will requite your loves. So, fare ye well.
+Upon the platform ’twixt eleven and twelve,
+I’ll visit you.
+
+ALL.
+Our duty to your honour.
+
+HAMLET.
+Your loves, as mine to you: farewell.
+
+[_Exeunt Horatio, Marcellus and Barnardo._]
+
+My father’s spirit in arms! All is not well;
+I doubt some foul play: would the night were come!
+Till then sit still, my soul: foul deeds will rise,
+Though all the earth o’erwhelm them, to men’s eyes.
+
+[_Exit._]
+
+ SCENE III. A room in Polonius’s house.
+
+Enter Laertes and Ophelia.
+
+LAERTES.
+My necessaries are embark’d. Farewell.
+And, sister, as the winds give benefit
+And convoy is assistant, do not sleep,
+But let me hear from you.
+
+OPHELIA.
+Do you doubt that?
+
+LAERTES.
+For Hamlet, and the trifling of his favour,
+Hold it a fashion and a toy in blood;
+A violet in the youth of primy nature,
+Forward, not permanent, sweet, not lasting;
+The perfume and suppliance of a minute;
+No more.
+
+OPHELIA.
+No more but so?
+
+LAERTES.
+Think it no more.
+For nature crescent does not grow alone
+In thews and bulk; but as this temple waxes,
+The inward service of the mind and soul
+Grows wide withal. Perhaps he loves you now,
+And now no soil nor cautel doth besmirch
+The virtue of his will; but you must fear,
+His greatness weigh’d, his will is not his own;
+For he himself is subject to his birth:
+He may not, as unvalu’d persons do,
+Carve for himself; for on his choice depends
+The sanctity and health of this whole state;
+And therefore must his choice be circumscrib’d
+Unto the voice and yielding of that body
+Whereof he is the head. Then if he says he loves you,
+It fits your wisdom so far to believe it
+As he in his particular act and place
+May give his saying deed; which is no further
+Than the main voice of Denmark goes withal.
+Then weigh what loss your honour may sustain
+If with too credent ear you list his songs,
+Or lose your heart, or your chaste treasure open
+To his unmaster’d importunity.
+Fear it, Ophelia, fear it, my dear sister;
+And keep you in the rear of your affection,
+Out of the shot and danger of desire.
+The chariest maid is prodigal enough
+If she unmask her beauty to the moon.
+Virtue itself ’scapes not calumnious strokes:
+The canker galls the infants of the spring
+Too oft before their buttons be disclos’d,
+And in the morn and liquid dew of youth
+Contagious blastments are most imminent.
+Be wary then, best safety lies in fear.
+Youth to itself rebels, though none else near.
+
+OPHELIA.
+I shall th’effect of this good lesson keep
+As watchman to my heart. But good my brother,
+Do not as some ungracious pastors do,
+Show me the steep and thorny way to heaven;
+Whilst like a puff’d and reckless libertine
+Himself the primrose path of dalliance treads,
+And recks not his own rede.
+
+LAERTES.
+O, fear me not.
+I stay too long. But here my father comes.
+
+Enter Polonius.
+
+A double blessing is a double grace;
+Occasion smiles upon a second leave.
+
+POLONIUS.
+Yet here, Laertes? Aboard, aboard, for shame.
+The wind sits in the shoulder of your sail,
+And you are stay’d for. There, my blessing with you.
+
+[_Laying his hand on Laertes’s head._]
+
+And these few precepts in thy memory
+Look thou character. Give thy thoughts no tongue,
+Nor any unproportion’d thought his act.
+Be thou familiar, but by no means vulgar.
+Those friends thou hast, and their adoption tried,
+Grapple them unto thy soul with hoops of steel;
+But do not dull thy palm with entertainment
+Of each new-hatch’d, unfledg’d comrade. Beware
+Of entrance to a quarrel; but being in,
+Bear’t that th’opposed may beware of thee.
+Give every man thine ear, but few thy voice:
+Take each man’s censure, but reserve thy judgement.
+Costly thy habit as thy purse can buy,
+But not express’d in fancy; rich, not gaudy:
+For the apparel oft proclaims the man;
+And they in France of the best rank and station
+Are of a most select and generous chief in that.
+Neither a borrower nor a lender be:
+For loan oft loses both itself and friend;
+And borrowing dulls the edge of husbandry.
+This above all: to thine own self be true;
+And it must follow, as the night the day,
+Thou canst not then be false to any man.
+Farewell: my blessing season this in thee.
+
+LAERTES.
+Most humbly do I take my leave, my lord.
+
+POLONIUS.
+The time invites you; go, your servants tend.
+
+LAERTES.
+Farewell, Ophelia, and remember well
+What I have said to you.
+
+OPHELIA.
+’Tis in my memory lock’d,
+And you yourself shall keep the key of it.
+
+LAERTES.
+Farewell.
+
+[_Exit._]
+
+POLONIUS.
+What is’t, Ophelia, he hath said to you?
+
+OPHELIA.
+So please you, something touching the Lord Hamlet.
+
+POLONIUS.
+Marry, well bethought:
+’Tis told me he hath very oft of late
+Given private time to you; and you yourself
+Have of your audience been most free and bounteous.
+If it be so,—as so ’tis put on me,
+And that in way of caution,—I must tell you
+You do not understand yourself so clearly
+As it behoves my daughter and your honour.
+What is between you? Give me up the truth.
+
+OPHELIA.
+He hath, my lord, of late made many tenders
+Of his affection to me.
+
+POLONIUS.
+Affection! Pooh! You speak like a green girl,
+Unsifted in such perilous circumstance.
+Do you believe his tenders, as you call them?
+
+OPHELIA.
+I do not know, my lord, what I should think.
+
+POLONIUS.
+Marry, I’ll teach you; think yourself a baby;
+That you have ta’en these tenders for true pay,
+Which are not sterling. Tender yourself more dearly;
+Or,—not to crack the wind of the poor phrase,
+Running it thus,—you’ll tender me a fool.
+
+OPHELIA.
+My lord, he hath importun’d me with love
+In honourable fashion.
+
+POLONIUS.
+Ay, fashion you may call it; go to, go to.
+
+OPHELIA.
+And hath given countenance to his speech, my lord,
+With almost all the holy vows of heaven.
+
+POLONIUS.
+Ay, springes to catch woodcocks. I do know,
+When the blood burns, how prodigal the soul
+Lends the tongue vows: these blazes, daughter,
+Giving more light than heat, extinct in both,
+Even in their promise, as it is a-making,
+You must not take for fire. From this time
+Be something scanter of your maiden presence;
+Set your entreatments at a higher rate
+Than a command to parley. For Lord Hamlet,
+Believe so much in him that he is young;
+And with a larger tether may he walk
+Than may be given you. In few, Ophelia,
+Do not believe his vows; for they are brokers,
+Not of that dye which their investments show,
+But mere implorators of unholy suits,
+Breathing like sanctified and pious bawds,
+The better to beguile. This is for all:
+I would not, in plain terms, from this time forth
+Have you so slander any moment leisure
+As to give words or talk with the Lord Hamlet.
+Look to’t, I charge you; come your ways.
+
+OPHELIA.
+I shall obey, my lord.
+
+[_Exeunt._]
+
+ SCENE IV. The platform.
+
+Enter Hamlet, Horatio and Marcellus.
+
+HAMLET.
+The air bites shrewdly; it is very cold.
+
+HORATIO.
+It is a nipping and an eager air.
+
+HAMLET.
+What hour now?
+
+HORATIO.
+I think it lacks of twelve.
+
+MARCELLUS.
+No, it is struck.
+
+HORATIO.
+Indeed? I heard it not. It then draws near the season
+Wherein the spirit held his wont to walk.
+
+[_A flourish of trumpets, and ordnance shot off within._]
+
+What does this mean, my lord?
+
+HAMLET.
+The King doth wake tonight and takes his rouse,
+Keeps wassail, and the swaggering upspring reels;
+And as he drains his draughts of Rhenish down,
+The kettle-drum and trumpet thus bray out
+The triumph of his pledge.
+
+HORATIO.
+Is it a custom?
+
+HAMLET.
+Ay marry is’t;
+And to my mind, though I am native here,
+And to the manner born, it is a custom
+More honour’d in the breach than the observance.
+This heavy-headed revel east and west
+Makes us traduc’d and tax’d of other nations:
+They clepe us drunkards, and with swinish phrase
+Soil our addition; and indeed it takes
+From our achievements, though perform’d at height,
+The pith and marrow of our attribute.
+So oft it chances in particular men
+That for some vicious mole of nature in them,
+As in their birth, wherein they are not guilty,
+Since nature cannot choose his origin,
+By their o’ergrowth of some complexion,
+Oft breaking down the pales and forts of reason;
+Or by some habit, that too much o’erleavens
+The form of plausive manners;—that these men,
+Carrying, I say, the stamp of one defect,
+Being Nature’s livery or Fortune’s star,—
+His virtues else,—be they as pure as grace,
+As infinite as man may undergo,
+Shall in the general censure take corruption
+From that particular fault. The dram of evil
+Doth all the noble substance of a doubt
+To his own scandal.
+
+HORATIO.
+Look, my lord, it comes!
+
+Enter Ghost.
+
+HAMLET.
+Angels and ministers of grace defend us!
+Be thou a spirit of health or goblin damn’d,
+Bring with thee airs from heaven or blasts from hell,
+Be thy intents wicked or charitable,
+Thou com’st in such a questionable shape
+That I will speak to thee. I’ll call thee Hamlet,
+King, father, royal Dane. O, answer me!
+Let me not burst in ignorance; but tell
+Why thy canoniz’d bones, hearsed in death,
+Have burst their cerements; why the sepulchre,
+Wherein we saw thee quietly inurn’d,
+Hath op’d his ponderous and marble jaws
+To cast thee up again! What may this mean,
+That thou, dead corse, again in complete steel,
+Revisit’st thus the glimpses of the moon,
+Making night hideous, and we fools of nature
+So horridly to shake our disposition
+With thoughts beyond the reaches of our souls?
+Say, why is this? Wherefore? What should we do?
+
+[_Ghost beckons Hamlet._]
+
+HORATIO.
+It beckons you to go away with it,
+As if it some impartment did desire
+To you alone.
+
+MARCELLUS.
+Look with what courteous action
+It waves you to a more removed ground.
+But do not go with it.
+
+HORATIO.
+No, by no means.
+
+HAMLET.
+It will not speak; then will I follow it.
+
+HORATIO.
+Do not, my lord.
+
+HAMLET.
+Why, what should be the fear?
+I do not set my life at a pin’s fee;
+And for my soul, what can it do to that,
+Being a thing immortal as itself?
+It waves me forth again. I’ll follow it.
+
+HORATIO.
+What if it tempt you toward the flood, my lord,
+Or to the dreadful summit of the cliff
+That beetles o’er his base into the sea,
+And there assume some other horrible form
+Which might deprive your sovereignty of reason,
+And draw you into madness? Think of it.
+The very place puts toys of desperation,
+Without more motive, into every brain
+That looks so many fathoms to the sea
+And hears it roar beneath.
+
+HAMLET.
+It waves me still.
+Go on, I’ll follow thee.
+
+MARCELLUS.
+You shall not go, my lord.
+
+HAMLET.
+Hold off your hands.
+
+HORATIO.
+Be rul’d; you shall not go.
+
+HAMLET.
+My fate cries out,
+And makes each petty artery in this body
+As hardy as the Nemean lion’s nerve.
+
+[_Ghost beckons._]
+
+Still am I call’d. Unhand me, gentlemen.
+
+[_Breaking free from them._]
+
+By heaven, I’ll make a ghost of him that lets me.
+I say, away!—Go on, I’ll follow thee.
+
+[_Exeunt Ghost and Hamlet._]
+
+HORATIO.
+He waxes desperate with imagination.
+
+MARCELLUS.
+Let’s follow; ’tis not fit thus to obey him.
+
+HORATIO.
+Have after. To what issue will this come?
+
+MARCELLUS.
+Something is rotten in the state of Denmark.
+
+HORATIO.
+Heaven will direct it.
+
+MARCELLUS.
+Nay, let’s follow him.
+
+[_Exeunt._]
+
+ SCENE V. A more remote part of the Castle.
+
+Enter Ghost and Hamlet.
+
+HAMLET.
+Whither wilt thou lead me? Speak, I’ll go no further.
+
+GHOST.
+Mark me.
+
+HAMLET.
+I will.
+
+GHOST.
+My hour is almost come,
+When I to sulph’rous and tormenting flames
+Must render up myself.
+
+HAMLET.
+Alas, poor ghost!
+
+GHOST.
+Pity me not, but lend thy serious hearing
+To what I shall unfold.
+
+HAMLET.
+Speak, I am bound to hear.
+
+GHOST.
+So art thou to revenge, when thou shalt hear.
+
+HAMLET.
+What?
+
+GHOST.
+I am thy father’s spirit,
+Doom’d for a certain term to walk the night,
+And for the day confin’d to fast in fires,
+Till the foul crimes done in my days of nature
+Are burnt and purg’d away. But that I am forbid
+To tell the secrets of my prison-house,
+I could a tale unfold whose lightest word
+Would harrow up thy soul; freeze thy young blood,
+Make thy two eyes like stars start from their spheres,
+Thy knotted and combined locks to part,
+And each particular hair to stand on end
+Like quills upon the fretful porpentine.
+But this eternal blazon must not be
+To ears of flesh and blood. List, list, O, list!
+If thou didst ever thy dear father love—
+
+HAMLET.
+O God!
+
+GHOST.
+Revenge his foul and most unnatural murder.
+
+HAMLET.
+Murder!
+
+GHOST.
+Murder most foul, as in the best it is;
+But this most foul, strange, and unnatural.
+
+HAMLET.
+Haste me to know’t, that I, with wings as swift
+As meditation or the thoughts of love
+May sweep to my revenge.
+
+GHOST.
+I find thee apt;
+And duller shouldst thou be than the fat weed
+That rots itself in ease on Lethe wharf,
+Wouldst thou not stir in this. Now, Hamlet, hear.
+’Tis given out that, sleeping in my orchard,
+A serpent stung me; so the whole ear of Denmark
+Is by a forged process of my death
+Rankly abus’d; but know, thou noble youth,
+The serpent that did sting thy father’s life
+Now wears his crown.
+
+HAMLET.
+O my prophetic soul!
+Mine uncle!
+
+GHOST.
+Ay, that incestuous, that adulterate beast,
+With witchcraft of his wit, with traitorous gifts,—
+O wicked wit, and gifts, that have the power
+So to seduce!—won to his shameful lust
+The will of my most seeming-virtuous queen.
+O Hamlet, what a falling off was there,
+From me, whose love was of that dignity
+That it went hand in hand even with the vow
+I made to her in marriage; and to decline
+Upon a wretch whose natural gifts were poor
+To those of mine. But virtue, as it never will be mov’d,
+Though lewdness court it in a shape of heaven;
+So lust, though to a radiant angel link’d,
+Will sate itself in a celestial bed
+And prey on garbage.
+But soft! methinks I scent the morning air;
+Brief let me be. Sleeping within my orchard,
+My custom always of the afternoon,
+Upon my secure hour thy uncle stole
+With juice of cursed hebenon in a vial,
+And in the porches of my ears did pour
+The leperous distilment, whose effect
+Holds such an enmity with blood of man
+That swift as quicksilver it courses through
+The natural gates and alleys of the body;
+And with a sudden vigour it doth posset
+And curd, like eager droppings into milk,
+The thin and wholesome blood. So did it mine;
+And a most instant tetter bark’d about,
+Most lazar-like, with vile and loathsome crust
+All my smooth body.
+Thus was I, sleeping, by a brother’s hand,
+Of life, of crown, of queen at once dispatch’d:
+Cut off even in the blossoms of my sin,
+Unhous’led, disappointed, unanel’d;
+No reckoning made, but sent to my account
+With all my imperfections on my head.
+O horrible! O horrible! most horrible!
+If thou hast nature in thee, bear it not;
+Let not the royal bed of Denmark be
+A couch for luxury and damned incest.
+But howsoever thou pursu’st this act,
+Taint not thy mind, nor let thy soul contrive
+Against thy mother aught; leave her to heaven,
+And to those thorns that in her bosom lodge,
+To prick and sting her. Fare thee well at once!
+The glow-worm shows the matin to be near,
+And ’gins to pale his uneffectual fire.
+Adieu, adieu, adieu. Remember me.
+
+[_Exit._]
+
+HAMLET.
+O all you host of heaven! O earth! What else?
+And shall I couple hell? O, fie! Hold, my heart;
+And you, my sinews, grow not instant old,
+But bear me stiffly up. Remember thee?
+Ay, thou poor ghost, while memory holds a seat
+In this distracted globe. Remember thee?
+Yea, from the table of my memory
+I’ll wipe away all trivial fond records,
+All saws of books, all forms, all pressures past,
+That youth and observation copied there;
+And thy commandment all alone shall live
+Within the book and volume of my brain,
+Unmix’d with baser matter. Yes, by heaven!
+O most pernicious woman!
+O villain, villain, smiling damned villain!
+My tables. Meet it is I set it down,
+That one may smile, and smile, and be a villain!
+At least I am sure it may be so in Denmark.
+
+[_Writing._]
+
+So, uncle, there you are. Now to my word;
+It is ‘Adieu, adieu, remember me.’
+I have sworn’t.
+
+HORATIO and MARCELLUS.
+[_Within._] My lord, my lord.
+
+MARCELLUS.
+[_Within._] Lord Hamlet.
+
+HORATIO.
+[_Within._] Heaven secure him.
+
+HAMLET.
+So be it!
+
+MARCELLUS.
+[_Within._] Illo, ho, ho, my lord!
+
+HAMLET.
+Hillo, ho, ho, boy! Come, bird, come.
+
+Enter Horatio and Marcellus.
+
+MARCELLUS.
+How is’t, my noble lord?
+
+HORATIO.
+What news, my lord?
+
+HAMLET.
+O, wonderful!
+
+HORATIO.
+Good my lord, tell it.
+
+HAMLET.
+No, you’ll reveal it.
+
+HORATIO.
+Not I, my lord, by heaven.
+
+MARCELLUS.
+Nor I, my lord.
+
+HAMLET.
+How say you then, would heart of man once think it?—
+But you’ll be secret?
+
+HORATIO and MARCELLUS.
+Ay, by heaven, my lord.
+
+HAMLET.
+There’s ne’er a villain dwelling in all Denmark
+But he’s an arrant knave.
+
+HORATIO.
+There needs no ghost, my lord, come from the grave
+To tell us this.
+
+HAMLET.
+Why, right; you are i’ the right;
+And so, without more circumstance at all,
+I hold it fit that we shake hands and part:
+You, as your business and desire shall point you,—
+For every man hath business and desire,
+Such as it is;—and for my own poor part,
+Look you, I’ll go pray.
+
+HORATIO.
+These are but wild and whirling words, my lord.
+
+HAMLET.
+I’m sorry they offend you, heartily;
+Yes faith, heartily.
+
+HORATIO.
+There’s no offence, my lord.
+
+HAMLET.
+Yes, by Saint Patrick, but there is, Horatio,
+And much offence too. Touching this vision here,
+It is an honest ghost, that let me tell you.
+For your desire to know what is between us,
+O’ermaster’t as you may. And now, good friends,
+As you are friends, scholars, and soldiers,
+Give me one poor request.
+
+HORATIO.
+What is’t, my lord? We will.
+
+HAMLET.
+Never make known what you have seen tonight.
+
+HORATIO and MARCELLUS.
+My lord, we will not.
+
+HAMLET.
+Nay, but swear’t.
+
+HORATIO.
+In faith, my lord, not I.
+
+MARCELLUS.
+Nor I, my lord, in faith.
+
+HAMLET.
+Upon my sword.
+
+MARCELLUS.
+We have sworn, my lord, already.
+
+HAMLET.
+Indeed, upon my sword, indeed.
+
+GHOST.
+[_Cries under the stage._] Swear.
+
+HAMLET.
+Ha, ha boy, sayst thou so? Art thou there, truepenny?
+Come on, you hear this fellow in the cellarage.
+Consent to swear.
+
+HORATIO.
+Propose the oath, my lord.
+
+HAMLET.
+Never to speak of this that you have seen.
+Swear by my sword.
+
+GHOST.
+[_Beneath._] Swear.
+
+HAMLET.
+_Hic et ubique?_ Then we’ll shift our ground.
+Come hither, gentlemen,
+And lay your hands again upon my sword.
+Never to speak of this that you have heard.
+Swear by my sword.
+
+GHOST.
+[_Beneath._] Swear.
+
+HAMLET.
+Well said, old mole! Canst work i’ th’earth so fast?
+A worthy pioner! Once more remove, good friends.
+
+HORATIO.
+O day and night, but this is wondrous strange.
+
+HAMLET.
+And therefore as a stranger give it welcome.
+There are more things in heaven and earth, Horatio,
+Than are dreamt of in your philosophy. But come,
+Here, as before, never, so help you mercy,
+How strange or odd soe’er I bear myself,—
+As I perchance hereafter shall think meet
+To put an antic disposition on—
+That you, at such times seeing me, never shall,
+With arms encumber’d thus, or this head-shake,
+Or by pronouncing of some doubtful phrase,
+As ‘Well, we know’, or ‘We could and if we would’,
+Or ‘If we list to speak’; or ‘There be and if they might’,
+Or such ambiguous giving out, to note
+That you know aught of me:—this not to do.
+So grace and mercy at your most need help you,
+Swear.
+
+GHOST.
+[_Beneath._] Swear.
+
+HAMLET.
+Rest, rest, perturbed spirit. So, gentlemen,
+With all my love I do commend me to you;
+And what so poor a man as Hamlet is
+May do t’express his love and friending to you,
+God willing, shall not lack. Let us go in together,
+And still your fingers on your lips, I pray.
+The time is out of joint. O cursed spite,
+That ever I was born to set it right.
+Nay, come, let’s go together.
+
+[_Exeunt._]
+
+
+
+
+ACT II
+
+SCENE I. A room in Polonius’s house.
+
+
+Enter Polonius and Reynaldo.
+
+POLONIUS.
+Give him this money and these notes, Reynaldo.
+
+REYNALDO.
+I will, my lord.
+
+POLONIUS.
+You shall do marvellous wisely, good Reynaldo,
+Before you visit him, to make inquiry
+Of his behaviour.
+
+REYNALDO.
+My lord, I did intend it.
+
+POLONIUS.
+Marry, well said; very well said. Look you, sir,
+Enquire me first what Danskers are in Paris;
+And how, and who, what means, and where they keep,
+What company, at what expense; and finding
+By this encompassment and drift of question,
+That they do know my son, come you more nearer
+Than your particular demands will touch it.
+Take you as ’twere some distant knowledge of him,
+As thus, ‘I know his father and his friends,
+And in part him’—do you mark this, Reynaldo?
+
+REYNALDO.
+Ay, very well, my lord.
+
+POLONIUS.
+‘And in part him, but,’ you may say, ‘not well;
+But if’t be he I mean, he’s very wild;
+Addicted so and so;’ and there put on him
+What forgeries you please; marry, none so rank
+As may dishonour him; take heed of that;
+But, sir, such wanton, wild, and usual slips
+As are companions noted and most known
+To youth and liberty.
+
+REYNALDO.
+As gaming, my lord?
+
+POLONIUS.
+Ay, or drinking, fencing, swearing,
+Quarrelling, drabbing. You may go so far.
+
+REYNALDO.
+My lord, that would dishonour him.
+
+POLONIUS.
+Faith no, as you may season it in the charge.
+You must not put another scandal on him,
+That he is open to incontinency;
+That’s not my meaning: but breathe his faults so quaintly
+That they may seem the taints of liberty;
+The flash and outbreak of a fiery mind,
+A savageness in unreclaimed blood,
+Of general assault.
+
+REYNALDO.
+But my good lord—
+
+POLONIUS.
+Wherefore should you do this?
+
+REYNALDO.
+Ay, my lord, I would know that.
+
+POLONIUS.
+Marry, sir, here’s my drift,
+And I believe it is a fetch of warrant.
+You laying these slight sullies on my son,
+As ’twere a thing a little soil’d i’ th’ working,
+Mark you,
+Your party in converse, him you would sound,
+Having ever seen in the prenominate crimes
+The youth you breathe of guilty, be assur’d
+He closes with you in this consequence;
+‘Good sir,’ or so; or ‘friend,’ or ‘gentleman’—
+According to the phrase or the addition
+Of man and country.
+
+REYNALDO.
+Very good, my lord.
+
+POLONIUS.
+And then, sir, does he this,—
+He does—What was I about to say?
+By the mass, I was about to say something. Where did I leave?
+
+REYNALDO.
+At ‘closes in the consequence.’
+At ‘friend or so,’ and ‘gentleman.’
+
+POLONIUS.
+At ‘closes in the consequence’ ay, marry!
+He closes with you thus: ‘I know the gentleman,
+I saw him yesterday, or t’other day,
+Or then, or then, with such and such; and, as you say,
+There was he gaming, there o’ertook in’s rouse,
+There falling out at tennis’: or perchance,
+‘I saw him enter such a house of sale’—
+_Videlicet_, a brothel, or so forth. See you now;
+Your bait of falsehood takes this carp of truth;
+And thus do we of wisdom and of reach,
+With windlasses, and with assays of bias,
+By indirections find directions out.
+So by my former lecture and advice
+Shall you my son. You have me, have you not?
+
+REYNALDO.
+My lord, I have.
+
+POLONIUS.
+God b’ wi’ you, fare you well.
+
+REYNALDO.
+Good my lord.
+
+POLONIUS.
+Observe his inclination in yourself.
+
+REYNALDO.
+I shall, my lord.
+
+POLONIUS.
+And let him ply his music.
+
+REYNALDO.
+Well, my lord.
+
+POLONIUS.
+Farewell.
+
+[_Exit Reynaldo._]
+
+Enter Ophelia.
+
+How now, Ophelia, what’s the matter?
+
+OPHELIA.
+Alas, my lord, I have been so affrighted.
+
+POLONIUS.
+With what, in the name of God?
+
+OPHELIA.
+My lord, as I was sewing in my chamber,
+Lord Hamlet, with his doublet all unbrac’d,
+No hat upon his head, his stockings foul’d,
+Ungart’red, and down-gyved to his ankle,
+Pale as his shirt, his knees knocking each other,
+And with a look so piteous in purport
+As if he had been loosed out of hell
+To speak of horrors, he comes before me.
+
+POLONIUS.
+Mad for thy love?
+
+OPHELIA.
+My lord, I do not know, but truly I do fear it.
+
+POLONIUS.
+What said he?
+
+OPHELIA.
+He took me by the wrist and held me hard;
+Then goes he to the length of all his arm;
+And with his other hand thus o’er his brow,
+He falls to such perusal of my face
+As he would draw it. Long stay’d he so,
+At last,—a little shaking of mine arm,
+And thrice his head thus waving up and down,
+He rais’d a sigh so piteous and profound
+As it did seem to shatter all his bulk
+And end his being. That done, he lets me go,
+And with his head over his shoulder turn’d
+He seem’d to find his way without his eyes,
+For out o’ doors he went without their help,
+And to the last bended their light on me.
+
+POLONIUS.
+Come, go with me. I will go seek the King.
+This is the very ecstasy of love,
+Whose violent property fordoes itself,
+And leads the will to desperate undertakings,
+As oft as any passion under heaven
+That does afflict our natures. I am sorry,—
+What, have you given him any hard words of late?
+
+OPHELIA.
+No, my good lord; but as you did command,
+I did repel his letters and denied
+His access to me.
+
+POLONIUS.
+That hath made him mad.
+I am sorry that with better heed and judgement
+I had not quoted him. I fear’d he did but trifle,
+And meant to wreck thee. But beshrew my jealousy!
+It seems it is as proper to our age
+To cast beyond ourselves in our opinions
+As it is common for the younger sort
+To lack discretion. Come, go we to the King.
+This must be known, which, being kept close, might move
+More grief to hide than hate to utter love.
+
+[_Exeunt._]
+
+ SCENE II. A room in the Castle.
+
+Enter King, Queen, Rosencrantz, Guildenstern and Attendants.
+
+KING.
+Welcome, dear Rosencrantz and Guildenstern.
+Moreover that we much did long to see you,
+The need we have to use you did provoke
+Our hasty sending. Something have you heard
+Of Hamlet’s transformation; so I call it,
+Since nor th’exterior nor the inward man
+Resembles that it was. What it should be,
+More than his father’s death, that thus hath put him
+So much from th’understanding of himself,
+I cannot dream of. I entreat you both
+That, being of so young days brought up with him,
+And since so neighbour’d to his youth and humour,
+That you vouchsafe your rest here in our court
+Some little time, so by your companies
+To draw him on to pleasures and to gather,
+So much as from occasion you may glean,
+Whether aught to us unknown afflicts him thus
+That, open’d, lies within our remedy.
+
+QUEEN.
+Good gentlemen, he hath much talk’d of you,
+And sure I am, two men there are not living
+To whom he more adheres. If it will please you
+To show us so much gentry and good will
+As to expend your time with us awhile,
+For the supply and profit of our hope,
+Your visitation shall receive such thanks
+As fits a king’s remembrance.
+
+ROSENCRANTZ.
+Both your majesties
+Might, by the sovereign power you have of us,
+Put your dread pleasures more into command
+Than to entreaty.
+
+GUILDENSTERN.
+We both obey,
+And here give up ourselves, in the full bent,
+To lay our service freely at your feet
+To be commanded.
+
+KING.
+Thanks, Rosencrantz and gentle Guildenstern.
+
+QUEEN.
+Thanks, Guildenstern and gentle Rosencrantz.
+And I beseech you instantly to visit
+My too much changed son. Go, some of you,
+And bring these gentlemen where Hamlet is.
+
+GUILDENSTERN.
+Heavens make our presence and our practices
+Pleasant and helpful to him.
+
+QUEEN.
+Ay, amen.
+
+[_Exeunt Rosencrantz, Guildenstern and some Attendants._]
+
+Enter Polonius.
+
+POLONIUS.
+Th’ambassadors from Norway, my good lord,
+Are joyfully return’d.
+
+KING.
+Thou still hast been the father of good news.
+
+POLONIUS.
+Have I, my lord? Assure you, my good liege,
+I hold my duty, as I hold my soul,
+Both to my God and to my gracious King:
+And I do think,—or else this brain of mine
+Hunts not the trail of policy so sure
+As it hath us’d to do—that I have found
+The very cause of Hamlet’s lunacy.
+
+KING.
+O speak of that, that do I long to hear.
+
+POLONIUS.
+Give first admittance to th’ambassadors;
+My news shall be the fruit to that great feast.
+
+KING.
+Thyself do grace to them, and bring them in.
+
+[_Exit Polonius._]
+
+He tells me, my sweet queen, that he hath found
+The head and source of all your son’s distemper.
+
+QUEEN.
+I doubt it is no other but the main,
+His father’s death and our o’erhasty marriage.
+
+KING.
+Well, we shall sift him.
+
+Enter Polonius with Voltemand and Cornelius.
+
+Welcome, my good friends!
+Say, Voltemand, what from our brother Norway?
+
+VOLTEMAND.
+Most fair return of greetings and desires.
+Upon our first, he sent out to suppress
+His nephew’s levies, which to him appear’d
+To be a preparation ’gainst the Polack;
+But better look’d into, he truly found
+It was against your Highness; whereat griev’d,
+That so his sickness, age, and impotence
+Was falsely borne in hand, sends out arrests
+On Fortinbras; which he, in brief, obeys,
+Receives rebuke from Norway; and in fine,
+Makes vow before his uncle never more
+To give th’assay of arms against your Majesty.
+Whereon old Norway, overcome with joy,
+Gives him three thousand crowns in annual fee,
+And his commission to employ those soldiers
+So levied as before, against the Polack:
+With an entreaty, herein further shown,
+[_Gives a paper._]
+That it might please you to give quiet pass
+Through your dominions for this enterprise,
+On such regards of safety and allowance
+As therein are set down.
+
+KING.
+It likes us well;
+And at our more consider’d time we’ll read,
+Answer, and think upon this business.
+Meantime we thank you for your well-took labour.
+Go to your rest, at night we’ll feast together:.
+Most welcome home.
+
+[_Exeunt Voltemand and Cornelius._]
+
+POLONIUS.
+This business is well ended.
+My liege and madam, to expostulate
+What majesty should be, what duty is,
+Why day is day, night night, and time is time
+Were nothing but to waste night, day and time.
+Therefore, since brevity is the soul of wit,
+And tediousness the limbs and outward flourishes,
+I will be brief. Your noble son is mad.
+Mad call I it; for to define true madness,
+What is’t but to be nothing else but mad?
+But let that go.
+
+QUEEN.
+More matter, with less art.
+
+POLONIUS.
+Madam, I swear I use no art at all.
+That he is mad, ’tis true: ’tis true ’tis pity;
+And pity ’tis ’tis true. A foolish figure,
+But farewell it, for I will use no art.
+Mad let us grant him then. And now remains
+That we find out the cause of this effect,
+Or rather say, the cause of this defect,
+For this effect defective comes by cause.
+Thus it remains, and the remainder thus. Perpend,
+I have a daughter—have whilst she is mine—
+Who in her duty and obedience, mark,
+Hath given me this. Now gather, and surmise.
+[_Reads._]
+_To the celestial, and my soul’s idol, the most beautified Ophelia_—
+That’s an ill phrase, a vile phrase; ‘beautified’ is a vile
+phrase: but you shall hear.
+[_Reads._]
+_these; in her excellent white bosom, these, &c._
+
+QUEEN.
+Came this from Hamlet to her?
+
+POLONIUS.
+Good madam, stay awhile; I will be faithful.
+[_Reads._]
+  _Doubt thou the stars are fire,
+     Doubt that the sun doth move,
+   Doubt truth to be a liar,
+     But never doubt I love.
+O dear Ophelia, I am ill at these numbers. I have not art to reckon my
+groans. But that I love thee best, O most best, believe it. Adieu.
+  Thine evermore, most dear lady, whilst this machine is to him,
+     HAMLET._
+This in obedience hath my daughter show’d me;
+And more above, hath his solicitings,
+As they fell out by time, by means, and place,
+All given to mine ear.
+
+KING.
+But how hath she receiv’d his love?
+
+POLONIUS.
+What do you think of me?
+
+KING.
+As of a man faithful and honourable.
+
+POLONIUS.
+I would fain prove so. But what might you think,
+When I had seen this hot love on the wing,
+As I perceiv’d it, I must tell you that,
+Before my daughter told me, what might you,
+Or my dear Majesty your queen here, think,
+If I had play’d the desk or table-book,
+Or given my heart a winking, mute and dumb,
+Or look’d upon this love with idle sight,
+What might you think? No, I went round to work,
+And my young mistress thus I did bespeak:
+‘Lord Hamlet is a prince, out of thy star.
+This must not be.’ And then I precepts gave her,
+That she should lock herself from his resort,
+Admit no messengers, receive no tokens.
+Which done, she took the fruits of my advice,
+And he, repulsed,—a short tale to make—
+Fell into a sadness, then into a fast,
+Thence to a watch, thence into a weakness,
+Thence to a lightness, and, by this declension,
+Into the madness wherein now he raves,
+And all we wail for.
+
+KING.
+Do you think ’tis this?
+
+QUEEN.
+It may be, very likely.
+
+POLONIUS.
+Hath there been such a time, I’d fain know that,
+That I have positively said ‘’Tis so,’
+When it prov’d otherwise?
+
+KING.
+Not that I know.
+
+POLONIUS.
+Take this from this, if this be otherwise.
+[_Points to his head and shoulder._]
+If circumstances lead me, I will find
+Where truth is hid, though it were hid indeed
+Within the centre.
+
+KING.
+How may we try it further?
+
+POLONIUS.
+You know sometimes he walks four hours together
+Here in the lobby.
+
+QUEEN.
+So he does indeed.
+
+POLONIUS.
+At such a time I’ll loose my daughter to him.
+Be you and I behind an arras then,
+Mark the encounter. If he love her not,
+And be not from his reason fall’n thereon,
+Let me be no assistant for a state,
+But keep a farm and carters.
+
+KING.
+We will try it.
+
+Enter Hamlet, reading.
+
+QUEEN.
+But look where sadly the poor wretch comes reading.
+
+POLONIUS.
+Away, I do beseech you, both away
+I’ll board him presently. O, give me leave.
+
+[_Exeunt King, Queen and Attendants._]
+
+How does my good Lord Hamlet?
+
+HAMLET.
+Well, God-a-mercy.
+
+POLONIUS.
+Do you know me, my lord?
+
+HAMLET.
+Excellent well. You are a fishmonger.
+
+POLONIUS.
+Not I, my lord.
+
+HAMLET.
+Then I would you were so honest a man.
+
+POLONIUS.
+Honest, my lord?
+
+HAMLET.
+Ay sir, to be honest, as this world goes, is to be one man picked out
+of ten thousand.
+
+POLONIUS.
+That’s very true, my lord.
+
+HAMLET.
+For if the sun breed maggots in a dead dog, being a good kissing
+carrion,—
+Have you a daughter?
+
+POLONIUS.
+I have, my lord.
+
+HAMLET.
+Let her not walk i’ th’ sun. Conception is a blessing, but not as your
+daughter may conceive. Friend, look to’t.
+
+POLONIUS.
+How say you by that? [_Aside._] Still harping on my daughter. Yet he
+knew me not at first; he said I was a fishmonger. He is far gone, far
+gone. And truly in my youth I suffered much extremity for love; very
+near this. I’ll speak to him again.—What do you read, my lord?
+
+HAMLET.
+Words, words, words.
+
+POLONIUS.
+What is the matter, my lord?
+
+HAMLET.
+Between who?
+
+POLONIUS.
+I mean the matter that you read, my lord.
+
+HAMLET.
+Slanders, sir. For the satirical slave says here that old men have grey
+beards; that their faces are wrinkled; their eyes purging thick amber
+and plum-tree gum; and that they have a plentiful lack of wit, together
+with most weak hams. All which, sir, though I most powerfully and
+potently believe, yet I hold it not honesty to have it thus set down.
+For you yourself, sir, should be old as I am, if like a crab you could
+go backward.
+
+POLONIUS.
+[_Aside._] Though this be madness, yet there is method in’t.—
+Will you walk out of the air, my lord?
+
+HAMLET.
+Into my grave?
+
+POLONIUS.
+Indeed, that is out o’ the air. [_Aside._] How pregnant sometimes his
+replies are! A happiness that often madness hits on, which reason and
+sanity could not so prosperously be delivered of. I will leave him and
+suddenly contrive the means of meeting between him and my daughter.
+My honourable lord, I will most humbly take my leave of you.
+
+HAMLET.
+You cannot, sir, take from me anything that I will more willingly part
+withal, except my life, except my life, except my life.
+
+POLONIUS.
+Fare you well, my lord.
+
+HAMLET.
+These tedious old fools.
+
+Enter Rosencrantz and Guildenstern.
+
+POLONIUS.
+You go to seek the Lord Hamlet; there he is.
+
+ROSENCRANTZ.
+[_To Polonius._] God save you, sir.
+
+[_Exit Polonius._]
+
+GUILDENSTERN.
+My honoured lord!
+
+ROSENCRANTZ.
+My most dear lord!
+
+HAMLET.
+My excellent good friends! How dost thou, Guildenstern? Ah,
+Rosencrantz. Good lads, how do ye both?
+
+ROSENCRANTZ.
+As the indifferent children of the earth.
+
+GUILDENSTERN.
+Happy in that we are not over-happy;
+On Fortune’s cap we are not the very button.
+
+HAMLET.
+Nor the soles of her shoe?
+
+ROSENCRANTZ.
+Neither, my lord.
+
+HAMLET.
+Then you live about her waist, or in the middle of her favours?
+
+GUILDENSTERN.
+Faith, her privates we.
+
+HAMLET.
+In the secret parts of Fortune? O, most true; she is a strumpet. What’s
+the news?
+
+ROSENCRANTZ.
+None, my lord, but that the world’s grown honest.
+
+HAMLET.
+Then is doomsday near. But your news is not true. Let me question more
+in particular. What have you, my good friends, deserved at the hands of
+Fortune, that she sends you to prison hither?
+
+GUILDENSTERN.
+Prison, my lord?
+
+HAMLET.
+Denmark’s a prison.
+
+ROSENCRANTZ.
+Then is the world one.
+
+HAMLET.
+A goodly one; in which there are many confines, wards, and dungeons,
+Denmark being one o’ th’ worst.
+
+ROSENCRANTZ.
+We think not so, my lord.
+
+HAMLET.
+Why, then ’tis none to you; for there is nothing either good or bad but
+thinking makes it so. To me it is a prison.
+
+ROSENCRANTZ.
+Why, then your ambition makes it one; ’tis too narrow for your mind.
+
+HAMLET.
+O God, I could be bounded in a nutshell, and count myself a king of
+infinite space, were it not that I have bad dreams.
+
+GUILDENSTERN.
+Which dreams, indeed, are ambition; for the very substance of the
+ambitious is merely the shadow of a dream.
+
+HAMLET.
+A dream itself is but a shadow.
+
+ROSENCRANTZ.
+Truly, and I hold ambition of so airy and light a quality that it is
+but a shadow’s shadow.
+
+HAMLET.
+Then are our beggars bodies, and our monarchs and outstretch’d heroes
+the beggars’ shadows. Shall we to th’ court? For, by my fay, I cannot
+reason.
+
+ROSENCRANTZ and GUILDENSTERN.
+We’ll wait upon you.
+
+HAMLET.
+No such matter. I will not sort you with the rest of my servants; for,
+to speak to you like an honest man, I am most dreadfully attended. But,
+in the beaten way of friendship, what make you at Elsinore?
+
+ROSENCRANTZ.
+To visit you, my lord, no other occasion.
+
+HAMLET.
+Beggar that I am, I am even poor in thanks; but I thank you. And sure,
+dear friends, my thanks are too dear a halfpenny. Were you not sent
+for? Is it your own inclining? Is it a free visitation? Come, deal
+justly with me. Come, come; nay, speak.
+
+GUILDENSTERN.
+What should we say, my lord?
+
+HAMLET.
+Why, anything. But to the purpose. You were sent for; and there is a
+kind of confession in your looks, which your modesties have not craft
+enough to colour. I know the good King and Queen have sent for you.
+
+ROSENCRANTZ.
+To what end, my lord?
+
+HAMLET.
+That you must teach me. But let me conjure you, by the rights of our
+fellowship, by the consonancy of our youth, by the obligation of our
+ever-preserved love, and by what more dear a better proposer could
+charge you withal, be even and direct with me, whether you were sent
+for or no.
+
+ROSENCRANTZ.
+[_To Guildenstern._] What say you?
+
+HAMLET.
+[_Aside._] Nay, then I have an eye of you. If you love me, hold not
+off.
+
+GUILDENSTERN.
+My lord, we were sent for.
+
+HAMLET.
+I will tell you why; so shall my anticipation prevent your discovery,
+and your secrecy to the King and Queen moult no feather. I have of
+late, but wherefore I know not, lost all my mirth, forgone all custom
+of exercises; and indeed, it goes so heavily with my disposition that
+this goodly frame the earth, seems to me a sterile promontory; this
+most excellent canopy the air, look you, this brave o’erhanging
+firmament, this majestical roof fretted with golden fire, why, it
+appears no other thing to me than a foul and pestilent congregation of
+vapours. What a piece of work is man, how noble in reason, how infinite
+in faculties, in form and moving, how express and admirable; in action
+how like an angel, in apprehension, how like a god: the beauty of the
+world, the paragon of animals. And yet, to me, what is this
+quintessence of dust? Man delights not me; no, nor woman neither,
+though by your smiling you seem to say so.
+
+ROSENCRANTZ.
+My lord, there was no such stuff in my thoughts.
+
+HAMLET.
+Why did you laugh then, when I said ‘Man delights not me’?
+
+ROSENCRANTZ.
+To think, my lord, if you delight not in man, what Lenten entertainment
+the players shall receive from you. We coted them on the way, and
+hither are they coming to offer you service.
+
+HAMLET.
+He that plays the king shall be welcome,—his Majesty shall have tribute
+of me; the adventurous knight shall use his foil and target; the lover
+shall not sigh gratis, the humorous man shall end his part in peace;
+the clown shall make those laugh whose lungs are tickle o’ th’ sere;
+and the lady shall say her mind freely, or the blank verse shall halt
+for’t. What players are they?
+
+ROSENCRANTZ.
+Even those you were wont to take such delight in—the tragedians of the
+city.
+
+HAMLET.
+How chances it they travel? Their residence, both in reputation and
+profit, was better both ways.
+
+ROSENCRANTZ.
+I think their inhibition comes by the means of the late innovation.
+
+HAMLET.
+Do they hold the same estimation they did when I was in the city? Are
+they so followed?
+
+ROSENCRANTZ.
+No, indeed, they are not.
+
+HAMLET.
+How comes it? Do they grow rusty?
+
+ROSENCRANTZ.
+Nay, their endeavour keeps in the wonted pace; but there is, sir, an
+aerie of children, little eyases, that cry out on the top of question,
+and are most tyrannically clapped for’t. These are now the fashion, and
+so berattle the common stages—so they call them—that many wearing
+rapiers are afraid of goose-quills and dare scarce come thither.
+
+HAMLET.
+What, are they children? Who maintains ’em? How are they escoted? Will
+they pursue the quality no longer than they can sing? Will they not say
+afterwards, if they should grow themselves to common players—as it is
+most like, if their means are no better—their writers do them wrong to
+make them exclaim against their own succession?
+
+ROSENCRANTZ.
+Faith, there has been much to do on both sides; and the nation holds it
+no sin to tarre them to controversy. There was for a while, no money
+bid for argument unless the poet and the player went to cuffs in the
+question.
+
+HAMLET.
+Is’t possible?
+
+GUILDENSTERN.
+O, there has been much throwing about of brains.
+
+HAMLET.
+Do the boys carry it away?
+
+ROSENCRANTZ.
+Ay, that they do, my lord. Hercules and his load too.
+
+HAMLET.
+It is not very strange; for my uncle is King of Denmark, and those that
+would make mouths at him while my father lived, give twenty, forty,
+fifty, a hundred ducats apiece for his picture in little. ’Sblood,
+there is something in this more than natural, if philosophy could find
+it out.
+
+[_Flourish of trumpets within._]
+
+GUILDENSTERN.
+There are the players.
+
+HAMLET.
+Gentlemen, you are welcome to Elsinore. Your hands, come. The
+appurtenance of welcome is fashion and ceremony. Let me comply with you
+in this garb, lest my extent to the players, which I tell you must show
+fairly outward, should more appear like entertainment than yours. You
+are welcome. But my uncle-father and aunt-mother are deceived.
+
+GUILDENSTERN.
+In what, my dear lord?
+
+HAMLET.
+I am but mad north-north-west. When the wind is southerly, I know a
+hawk from a handsaw.
+
+Enter Polonius.
+
+POLONIUS.
+Well be with you, gentlemen.
+
+HAMLET.
+Hark you, Guildenstern, and you too, at each ear a hearer. That great
+baby you see there is not yet out of his swaddling clouts.
+
+ROSENCRANTZ.
+Happily he’s the second time come to them; for they say an old man is
+twice a child.
+
+HAMLET.
+I will prophesy he comes to tell me of the players. Mark it.—You say
+right, sir: for a Monday morning ’twas so indeed.
+
+POLONIUS.
+My lord, I have news to tell you.
+
+HAMLET.
+My lord, I have news to tell you. When Roscius was an actor in Rome—
+
+POLONIUS.
+The actors are come hither, my lord.
+
+HAMLET.
+Buzz, buzz.
+
+POLONIUS.
+Upon my honour.
+
+HAMLET.
+Then came each actor on his ass—
+
+POLONIUS.
+The best actors in the world, either for tragedy, comedy, history,
+pastoral, pastoral-comical, historical-pastoral, tragical-historical,
+tragical-comical-historical-pastoral, scene individable, or poem
+unlimited. Seneca cannot be too heavy, nor Plautus too light, for the
+law of writ and the liberty. These are the only men.
+
+HAMLET.
+O Jephthah, judge of Israel, what a treasure hadst thou!
+
+POLONIUS.
+What treasure had he, my lord?
+
+HAMLET.
+Why—
+   ’One fair daughter, and no more,
+   The which he loved passing well.’
+
+POLONIUS.
+[_Aside._] Still on my daughter.
+
+HAMLET.
+Am I not i’ th’ right, old Jephthah?
+
+POLONIUS.
+If you call me Jephthah, my lord, I have a daughter that I love passing
+well.
+
+HAMLET.
+Nay, that follows not.
+
+POLONIUS.
+What follows then, my lord?
+
+HAMLET.
+Why,
+   As by lot, God wot,
+and then, you know,
+   It came to pass, as most like it was.
+The first row of the pious chanson will show you more. For look where
+my abridgement comes.
+
+Enter four or five Players.
+
+You are welcome, masters, welcome all. I am glad to see thee well.
+Welcome, good friends. O, my old friend! Thy face is valanc’d since I
+saw thee last. Com’st thou to beard me in Denmark? What, my young lady
+and mistress! By’r lady, your ladyship is nearer to heaven than when I
+saw you last, by the altitude of a chopine. Pray God your voice, like a
+piece of uncurrent gold, be not cracked within the ring. Masters, you
+are all welcome. We’ll e’en to’t like French falconers, fly at anything
+we see. We’ll have a speech straight. Come, give us a taste of your
+quality. Come, a passionate speech.
+
+FIRST PLAYER.
+What speech, my lord?
+
+HAMLET.
+I heard thee speak me a speech once, but it was never acted, or if it
+was, not above once, for the play, I remember, pleased not the million,
+’twas caviare to the general. But it was—as I received it, and others,
+whose judgements in such matters cried in the top of mine—an excellent
+play, well digested in the scenes, set down with as much modesty as
+cunning. I remember one said there were no sallets in the lines to make
+the matter savoury, nor no matter in the phrase that might indite the
+author of affectation, but called it an honest method, as wholesome as
+sweet, and by very much more handsome than fine. One speech in it, I
+chiefly loved. ’Twas Aeneas’ tale to Dido, and thereabout of it
+especially where he speaks of Priam’s slaughter. If it live in your
+memory, begin at this line, let me see, let me see:
+   _The rugged Pyrrhus, like th’ Hyrcanian beast,—_
+It is not so: it begins with Pyrrhus—
+   _The rugged Pyrrhus, he whose sable arms,
+   Black as his purpose, did the night resemble
+   When he lay couched in the ominous horse,
+   Hath now this dread and black complexion smear’d
+   With heraldry more dismal. Head to foot
+   Now is he total gules, horridly trick’d
+   With blood of fathers, mothers, daughters, sons,
+   Bak’d and impasted with the parching streets,
+   That lend a tyrannous and a damned light
+   To their vile murders. Roasted in wrath and fire,
+   And thus o’ersized with coagulate gore,
+   With eyes like carbuncles, the hellish Pyrrhus
+   Old grandsire Priam seeks._
+So, proceed you.
+
+POLONIUS.
+’Fore God, my lord, well spoken, with good accent and good discretion.
+
+FIRST PLAYER.
+   _Anon he finds him,
+   Striking too short at Greeks. His antique sword,
+   Rebellious to his arm, lies where it falls,
+   Repugnant to command. Unequal match’d,
+   Pyrrhus at Priam drives, in rage strikes wide;
+   But with the whiff and wind of his fell sword
+   Th’unnerved father falls. Then senseless Ilium,
+   Seeming to feel this blow, with flaming top
+   Stoops to his base, and with a hideous crash
+   Takes prisoner Pyrrhus’ ear. For lo, his sword,
+   Which was declining on the milky head
+   Of reverend Priam, seem’d i’ th’air to stick.
+   So, as a painted tyrant, Pyrrhus stood,
+   And like a neutral to his will and matter,
+   Did nothing.
+   But as we often see against some storm,
+   A silence in the heavens, the rack stand still,
+   The bold winds speechless, and the orb below
+   As hush as death, anon the dreadful thunder
+   Doth rend the region; so after Pyrrhus’ pause,
+   Aroused vengeance sets him new a-work,
+   And never did the Cyclops’ hammers fall
+   On Mars’s armour, forg’d for proof eterne,
+   With less remorse than Pyrrhus’ bleeding sword
+   Now falls on Priam.
+   Out, out, thou strumpet Fortune! All you gods,
+   In general synod, take away her power;
+   Break all the spokes and fellies from her wheel,
+   And bowl the round nave down the hill of heaven,
+   As low as to the fiends._
+
+POLONIUS.
+This is too long.
+
+HAMLET.
+It shall to the barber’s, with your beard.—Prithee say on.
+He’s for a jig or a tale of bawdry, or he sleeps.
+Say on; come to Hecuba.
+
+FIRST PLAYER.
+   _But who, O who, had seen the mobled queen,—_
+
+HAMLET.
+‘The mobled queen’?
+
+POLONIUS.
+That’s good! ‘Mobled queen’ is good.
+
+FIRST PLAYER.
+   _Run barefoot up and down, threat’ning the flames
+   With bisson rheum. A clout upon that head
+   Where late the diadem stood, and for a robe,
+   About her lank and all o’erteemed loins,
+   A blanket, in th’alarm of fear caught up—
+   Who this had seen, with tongue in venom steep’d,
+   ’Gainst Fortune’s state would treason have pronounc’d.
+   But if the gods themselves did see her then,
+   When she saw Pyrrhus make malicious sport
+   In mincing with his sword her husband’s limbs,
+   The instant burst of clamour that she made,—
+   Unless things mortal move them not at all,—
+   Would have made milch the burning eyes of heaven,
+   And passion in the gods._
+
+POLONIUS.
+Look, where he has not turn’d his colour, and has tears in’s eyes. Pray
+you, no more.
+
+HAMLET.
+’Tis well. I’ll have thee speak out the rest of this soon.—Good my
+lord, will you see the players well bestowed? Do you hear, let them be
+well used; for they are the abstracts and brief chronicles of the time.
+After your death you were better have a bad epitaph than their ill
+report while you live.
+
+POLONIUS.
+My lord, I will use them according to their desert.
+
+HAMLET.
+God’s bodikin, man, much better. Use every man after his desert, and who
+should ’scape whipping? Use them after your own honour and dignity. The
+less they deserve, the more merit is in your bounty. Take them in.
+
+POLONIUS.
+Come, sirs.
+
+HAMLET.
+Follow him, friends. We’ll hear a play tomorrow.
+
+[_Exeunt Polonius with all the Players but the First._]
+
+Dost thou hear me, old friend? Can you play _The Murder of Gonzago_?
+
+FIRST PLAYER.
+Ay, my lord.
+
+HAMLET.
+We’ll ha’t tomorrow night. You could for a need study a speech of some
+dozen or sixteen lines, which I would set down and insert in’t, could
+you not?
+
+FIRST PLAYER.
+Ay, my lord.
+
+HAMLET.
+Very well. Follow that lord, and look you mock him not.
+
+[_Exit First Player._]
+
+[_To Rosencrantz and Guildenstern_] My good friends, I’ll leave you
+till night. You are welcome to Elsinore.
+
+ROSENCRANTZ.
+Good my lord.
+
+[_Exeunt Rosencrantz and Guildenstern._]
+
+HAMLET.
+Ay, so, God b’ wi’ ye. Now I am alone.
+O what a rogue and peasant slave am I!
+Is it not monstrous that this player here,
+But in a fiction, in a dream of passion,
+Could force his soul so to his own conceit
+That from her working all his visage wan’d;
+Tears in his eyes, distraction in’s aspect,
+A broken voice, and his whole function suiting
+With forms to his conceit? And all for nothing!
+For Hecuba?
+What’s Hecuba to him, or he to Hecuba,
+That he should weep for her? What would he do,
+Had he the motive and the cue for passion
+That I have? He would drown the stage with tears
+And cleave the general ear with horrid speech;
+Make mad the guilty, and appal the free,
+Confound the ignorant, and amaze indeed,
+The very faculties of eyes and ears. Yet I,
+A dull and muddy-mettled rascal, peak
+Like John-a-dreams, unpregnant of my cause,
+And can say nothing. No, not for a king
+Upon whose property and most dear life
+A damn’d defeat was made. Am I a coward?
+Who calls me villain, breaks my pate across?
+Plucks off my beard and blows it in my face?
+Tweaks me by the nose, gives me the lie i’ th’ throat
+As deep as to the lungs? Who does me this?
+Ha! ’Swounds, I should take it: for it cannot be
+But I am pigeon-liver’d, and lack gall
+To make oppression bitter, or ere this
+I should have fatted all the region kites
+With this slave’s offal. Bloody, bawdy villain!
+Remorseless, treacherous, lecherous, kindless villain!
+Oh vengeance!
+Why, what an ass am I! This is most brave,
+That I, the son of a dear father murder’d,
+Prompted to my revenge by heaven and hell,
+Must, like a whore, unpack my heart with words
+And fall a-cursing like a very drab,
+A scullion! Fie upon’t! Foh!
+About, my brain! I have heard
+That guilty creatures sitting at a play,
+Have by the very cunning of the scene,
+Been struck so to the soul that presently
+They have proclaim’d their malefactions.
+For murder, though it have no tongue, will speak
+With most miraculous organ. I’ll have these players
+Play something like the murder of my father
+Before mine uncle. I’ll observe his looks;
+I’ll tent him to the quick. If he but blench,
+I know my course. The spirit that I have seen
+May be the devil, and the devil hath power
+T’assume a pleasing shape, yea, and perhaps
+Out of my weakness and my melancholy,
+As he is very potent with such spirits,
+Abuses me to damn me. I’ll have grounds
+More relative than this. The play’s the thing
+Wherein I’ll catch the conscience of the King.
+
+[_Exit._]
+
+
+
+
+ACT III
+
+SCENE I. A room in the Castle.
+
+
+Enter King, Queen, Polonius, Ophelia, Rosencrantz and Guildenstern.
+
+KING.
+And can you by no drift of circumstance
+Get from him why he puts on this confusion,
+Grating so harshly all his days of quiet
+With turbulent and dangerous lunacy?
+
+ROSENCRANTZ.
+He does confess he feels himself distracted,
+But from what cause he will by no means speak.
+
+GUILDENSTERN.
+Nor do we find him forward to be sounded,
+But with a crafty madness keeps aloof
+When we would bring him on to some confession
+Of his true state.
+
+QUEEN.
+Did he receive you well?
+
+ROSENCRANTZ.
+Most like a gentleman.
+
+GUILDENSTERN.
+But with much forcing of his disposition.
+
+ROSENCRANTZ.
+Niggard of question, but of our demands,
+Most free in his reply.
+
+QUEEN.
+Did you assay him to any pastime?
+
+ROSENCRANTZ.
+Madam, it so fell out that certain players
+We o’er-raught on the way. Of these we told him,
+And there did seem in him a kind of joy
+To hear of it. They are about the court,
+And, as I think, they have already order
+This night to play before him.
+
+POLONIUS.
+’Tis most true;
+And he beseech’d me to entreat your Majesties
+To hear and see the matter.
+
+KING.
+With all my heart; and it doth much content me
+To hear him so inclin’d.
+Good gentlemen, give him a further edge,
+And drive his purpose on to these delights.
+
+ROSENCRANTZ.
+We shall, my lord.
+
+[_Exeunt Rosencrantz and Guildenstern._]
+
+KING.
+Sweet Gertrude, leave us too,
+For we have closely sent for Hamlet hither,
+That he, as ’twere by accident, may here
+Affront Ophelia.
+Her father and myself, lawful espials,
+Will so bestow ourselves that, seeing unseen,
+We may of their encounter frankly judge,
+And gather by him, as he is behav’d,
+If’t be th’affliction of his love or no
+That thus he suffers for.
+
+QUEEN.
+I shall obey you.
+And for your part, Ophelia, I do wish
+That your good beauties be the happy cause
+Of Hamlet’s wildness: so shall I hope your virtues
+Will bring him to his wonted way again,
+To both your honours.
+
+OPHELIA.
+Madam, I wish it may.
+
+[_Exit Queen._]
+
+POLONIUS.
+Ophelia, walk you here.—Gracious, so please you,
+We will bestow ourselves.—[_To Ophelia._] Read on this book,
+That show of such an exercise may colour
+Your loneliness.—We are oft to blame in this,
+’Tis too much prov’d, that with devotion’s visage
+And pious action we do sugar o’er
+The devil himself.
+
+KING.
+[_Aside._] O ’tis too true!
+How smart a lash that speech doth give my conscience!
+The harlot’s cheek, beautied with plastering art,
+Is not more ugly to the thing that helps it
+Than is my deed to my most painted word.
+O heavy burden!
+
+POLONIUS.
+I hear him coming. Let’s withdraw, my lord.
+
+[_Exeunt King and Polonius._]
+
+Enter Hamlet.
+
+HAMLET.
+To be, or not to be, that is the question:
+Whether ’tis nobler in the mind to suffer
+The slings and arrows of outrageous fortune,
+Or to take arms against a sea of troubles,
+And by opposing end them? To die—to sleep,
+No more; and by a sleep to say we end
+The heart-ache, and the thousand natural shocks
+That flesh is heir to: ’tis a consummation
+Devoutly to be wish’d. To die, to sleep.
+To sleep, perchance to dream—ay, there’s the rub,
+For in that sleep of death what dreams may come,
+When we have shuffled off this mortal coil,
+Must give us pause. There’s the respect
+That makes calamity of so long life.
+For who would bear the whips and scorns of time,
+The oppressor’s wrong, the proud man’s contumely,
+The pangs of dispriz’d love, the law’s delay,
+The insolence of office, and the spurns
+That patient merit of the unworthy takes,
+When he himself might his quietus make
+With a bare bodkin? Who would these fardels bear,
+To grunt and sweat under a weary life,
+But that the dread of something after death,
+The undiscover’d country, from whose bourn
+No traveller returns, puzzles the will,
+And makes us rather bear those ills we have
+Than fly to others that we know not of?
+Thus conscience does make cowards of us all,
+And thus the native hue of resolution
+Is sicklied o’er with the pale cast of thought,
+And enterprises of great pith and moment,
+With this regard their currents turn awry
+And lose the name of action. Soft you now,
+The fair Ophelia! Nymph, in thy orisons
+Be all my sins remember’d.
+
+OPHELIA.
+Good my lord,
+How does your honour for this many a day?
+
+HAMLET.
+I humbly thank you; well, well, well.
+
+OPHELIA.
+My lord, I have remembrances of yours
+That I have longed long to re-deliver.
+I pray you, now receive them.
+
+HAMLET.
+No, not I.
+I never gave you aught.
+
+OPHELIA.
+My honour’d lord, you know right well you did,
+And with them words of so sweet breath compos’d
+As made the things more rich; their perfume lost,
+Take these again; for to the noble mind
+Rich gifts wax poor when givers prove unkind.
+There, my lord.
+
+HAMLET.
+Ha, ha! Are you honest?
+
+OPHELIA.
+My lord?
+
+HAMLET.
+Are you fair?
+
+OPHELIA.
+What means your lordship?
+
+HAMLET.
+That if you be honest and fair, your honesty should admit no discourse
+to your beauty.
+
+OPHELIA.
+Could beauty, my lord, have better commerce than with honesty?
+
+HAMLET.
+Ay, truly; for the power of beauty will sooner transform honesty from
+what it is to a bawd than the force of honesty can translate beauty
+into his likeness. This was sometime a paradox, but now the time gives
+it proof. I did love you once.
+
+OPHELIA.
+Indeed, my lord, you made me believe so.
+
+HAMLET.
+You should not have believed me; for virtue cannot so inoculate our old
+stock but we shall relish of it. I loved you not.
+
+OPHELIA.
+I was the more deceived.
+
+HAMLET.
+Get thee to a nunnery. Why wouldst thou be a breeder of sinners? I am
+myself indifferent honest; but yet I could accuse me of such things
+that it were better my mother had not borne me. I am very proud,
+revengeful, ambitious, with more offences at my beck than I have
+thoughts to put them in, imagination to give them shape, or time to act
+them in. What should such fellows as I do crawling between earth and
+heaven? We are arrant knaves all, believe none of us. Go thy ways to a
+nunnery. Where’s your father?
+
+OPHELIA.
+At home, my lord.
+
+HAMLET.
+Let the doors be shut upon him, that he may play the fool nowhere but
+in’s own house. Farewell.
+
+OPHELIA.
+O help him, you sweet heavens!
+
+HAMLET.
+If thou dost marry, I’ll give thee this plague for thy dowry. Be thou
+as chaste as ice, as pure as snow, thou shalt not escape calumny. Get
+thee to a nunnery, go: farewell. Or if thou wilt needs marry, marry a
+fool; for wise men know well enough what monsters you make of them. To
+a nunnery, go; and quickly too. Farewell.
+
+OPHELIA.
+O heavenly powers, restore him!
+
+HAMLET.
+I have heard of your paintings too, well enough. God hath given you one
+face, and you make yourselves another. You jig, you amble, and you
+lisp, and nickname God’s creatures, and make your wantonness your
+ignorance. Go to, I’ll no more on’t, it hath made me mad. I say, we
+will have no more marriages. Those that are married already, all but
+one, shall live; the rest shall keep as they are. To a nunnery, go.
+
+[_Exit._]
+
+OPHELIA.
+O, what a noble mind is here o’erthrown!
+The courtier’s, soldier’s, scholar’s, eye, tongue, sword,
+Th’expectancy and rose of the fair state,
+The glass of fashion and the mould of form,
+Th’observ’d of all observers, quite, quite down!
+And I, of ladies most deject and wretched,
+That suck’d the honey of his music vows,
+Now see that noble and most sovereign reason,
+Like sweet bells jangled out of tune and harsh,
+That unmatch’d form and feature of blown youth
+Blasted with ecstasy. O woe is me,
+T’have seen what I have seen, see what I see.
+
+Enter King and Polonius.
+
+KING.
+Love? His affections do not that way tend,
+Nor what he spake, though it lack’d form a little,
+Was not like madness. There’s something in his soul
+O’er which his melancholy sits on brood,
+And I do doubt the hatch and the disclose
+Will be some danger, which for to prevent,
+I have in quick determination
+Thus set it down: he shall with speed to England
+For the demand of our neglected tribute:
+Haply the seas and countries different,
+With variable objects, shall expel
+This something settled matter in his heart,
+Whereon his brains still beating puts him thus
+From fashion of himself. What think you on’t?
+
+POLONIUS.
+It shall do well. But yet do I believe
+The origin and commencement of his grief
+Sprung from neglected love. How now, Ophelia?
+You need not tell us what Lord Hamlet said,
+We heard it all. My lord, do as you please,
+But if you hold it fit, after the play,
+Let his queen mother all alone entreat him
+To show his grief, let her be round with him,
+And I’ll be plac’d, so please you, in the ear
+Of all their conference. If she find him not,
+To England send him; or confine him where
+Your wisdom best shall think.
+
+KING.
+It shall be so.
+Madness in great ones must not unwatch’d go.
+
+[_Exeunt._]
+
+ SCENE II. A hall in the Castle.
+
+Enter Hamlet and certain Players.
+
+HAMLET.
+Speak the speech, I pray you, as I pronounced it to you, trippingly on
+the tongue. But if you mouth it, as many of your players do, I had as
+lief the town-crier spoke my lines. Nor do not saw the air too much
+with your hand, thus, but use all gently; for in the very torrent,
+tempest, and, as I may say, whirlwind of passion, you must acquire and
+beget a temperance that may give it smoothness. O, it offends me to the
+soul to hear a robustious periwig-pated fellow tear a passion to
+tatters, to very rags, to split the ears of the groundlings, who, for
+the most part, are capable of nothing but inexplicable dumb shows and
+noise. I would have such a fellow whipped for o’erdoing Termagant. It
+out-Herods Herod. Pray you avoid it.
+
+FIRST PLAYER.
+I warrant your honour.
+
+HAMLET.
+Be not too tame neither; but let your own discretion be your tutor.
+Suit the action to the word, the word to the action, with this special
+observance, that you o’erstep not the modesty of nature; for anything
+so overdone is from the purpose of playing, whose end, both at the
+first and now, was and is, to hold as ’twere the mirror up to nature;
+to show virtue her own feature, scorn her own image, and the very age
+and body of the time his form and pressure. Now, this overdone, or come
+tardy off, though it make the unskilful laugh, cannot but make the
+judicious grieve; the censure of the which one must in your allowance
+o’erweigh a whole theatre of others. O, there be players that I have
+seen play—and heard others praise, and that highly—not to speak it
+profanely, that, neither having the accent of Christians, nor the gait
+of Christian, pagan, nor man, have so strutted and bellowed that I have
+thought some of Nature’s journeymen had made men, and not made them
+well, they imitated humanity so abominably.
+
+FIRST PLAYER.
+I hope we have reform’d that indifferently with us, sir.
+
+HAMLET.
+O reform it altogether. And let those that play your clowns speak no
+more than is set down for them. For there be of them that will
+themselves laugh, to set on some quantity of barren spectators to laugh
+too, though in the meantime some necessary question of the play be then
+to be considered. That’s villainous, and shows a most pitiful ambition
+in the fool that uses it. Go make you ready.
+
+[_Exeunt Players._]
+
+Enter Polonius, Rosencrantz and Guildenstern.
+
+How now, my lord?
+Will the King hear this piece of work?
+
+POLONIUS.
+And the Queen too, and that presently.
+
+HAMLET.
+Bid the players make haste.
+
+[_Exit Polonius._]
+
+Will you two help to hasten them?
+
+ROSENCRANTZ and GUILDENSTERN.
+We will, my lord.
+
+[_Exeunt Rosencrantz and Guildenstern._]
+
+HAMLET.
+What ho, Horatio!
+
+Enter Horatio.
+
+HORATIO.
+Here, sweet lord, at your service.
+
+HAMLET.
+Horatio, thou art e’en as just a man
+As e’er my conversation cop’d withal.
+
+HORATIO.
+O my dear lord.
+
+HAMLET.
+Nay, do not think I flatter;
+For what advancement may I hope from thee,
+That no revenue hast, but thy good spirits
+To feed and clothe thee? Why should the poor be flatter’d?
+No, let the candied tongue lick absurd pomp,
+And crook the pregnant hinges of the knee
+Where thrift may follow fawning. Dost thou hear?
+Since my dear soul was mistress of her choice,
+And could of men distinguish, her election
+Hath seal’d thee for herself. For thou hast been
+As one, in suffering all, that suffers nothing,
+A man that Fortune’s buffets and rewards
+Hast ta’en with equal thanks. And blessed are those
+Whose blood and judgement are so well co-mingled
+That they are not a pipe for Fortune’s finger
+To sound what stop she please. Give me that man
+That is not passion’s slave, and I will wear him
+In my heart’s core, ay, in my heart of heart,
+As I do thee. Something too much of this.
+There is a play tonight before the King.
+One scene of it comes near the circumstance
+Which I have told thee, of my father’s death.
+I prithee, when thou see’st that act a-foot,
+Even with the very comment of thy soul
+Observe mine uncle. If his occulted guilt
+Do not itself unkennel in one speech,
+It is a damned ghost that we have seen;
+And my imaginations are as foul
+As Vulcan’s stithy. Give him heedful note;
+For I mine eyes will rivet to his face;
+And after we will both our judgements join
+In censure of his seeming.
+
+HORATIO.
+Well, my lord.
+If he steal aught the whilst this play is playing,
+And ’scape detecting, I will pay the theft.
+
+HAMLET.
+They are coming to the play. I must be idle.
+Get you a place.
+
+Danish march. A flourish. Enter King, Queen, Polonius, Ophelia,
+Rosencrantz, Guildenstern and others.
+
+KING.
+How fares our cousin Hamlet?
+
+HAMLET.
+Excellent, i’ faith; of the chameleon’s dish: I eat the air,
+promise-crammed: you cannot feed capons so.
+
+KING.
+I have nothing with this answer, Hamlet; these words are not mine.
+
+HAMLET.
+No, nor mine now. [_To Polonius._] My lord, you play’d once i’
+th’university, you say?
+
+POLONIUS.
+That did I, my lord, and was accounted a good actor.
+
+HAMLET.
+What did you enact?
+
+POLONIUS.
+I did enact Julius Caesar. I was kill’d i’ th’ Capitol. Brutus killed
+me.
+
+HAMLET.
+It was a brute part of him to kill so capital a calf there. Be the
+players ready?
+
+ROSENCRANTZ.
+Ay, my lord; they stay upon your patience.
+
+QUEEN.
+Come hither, my dear Hamlet, sit by me.
+
+HAMLET.
+No, good mother, here’s metal more attractive.
+
+POLONIUS.
+[_To the King._] O ho! do you mark that?
+
+HAMLET.
+Lady, shall I lie in your lap?
+
+[_Lying down at Ophelia’s feet._]
+
+OPHELIA.
+No, my lord.
+
+HAMLET.
+I mean, my head upon your lap?
+
+OPHELIA.
+Ay, my lord.
+
+HAMLET.
+Do you think I meant country matters?
+
+OPHELIA.
+I think nothing, my lord.
+
+HAMLET.
+That’s a fair thought to lie between maids’ legs.
+
+OPHELIA.
+What is, my lord?
+
+HAMLET.
+Nothing.
+
+OPHELIA.
+You are merry, my lord.
+
+HAMLET.
+Who, I?
+
+OPHELIA.
+Ay, my lord.
+
+HAMLET.
+O God, your only jig-maker! What should a man do but be merry? For look
+you how cheerfully my mother looks, and my father died within’s two
+hours.
+
+OPHELIA.
+Nay, ’tis twice two months, my lord.
+
+HAMLET.
+So long? Nay then, let the devil wear black, for I’ll have a suit of
+sables. O heavens! die two months ago, and not forgotten yet? Then
+there’s hope a great man’s memory may outlive his life half a year. But
+by’r lady, he must build churches then; or else shall he suffer not
+thinking on, with the hobby-horse, whose epitaph is ‘For, O, for O, the
+hobby-horse is forgot!’
+
+Trumpets sound. The dumb show enters.
+
+_Enter a King and a Queen very lovingly; the Queen embracing him and he
+her. She kneels, and makes show of protestation unto him. He takes her
+up, and declines his head upon her neck. Lays him down upon a bank of
+flowers. She, seeing him asleep, leaves him. Anon comes in a fellow,
+takes off his crown, kisses it, pours poison in the King’s ears, and
+exits. The Queen returns, finds the King dead, and makes passionate
+action. The Poisoner with some three or four Mutes, comes in again,
+seeming to lament with her. The dead body is carried away. The Poisoner
+woos the Queen with gifts. She seems loth and unwilling awhile, but in
+the end accepts his love._
+
+[_Exeunt._]
+
+OPHELIA.
+What means this, my lord?
+
+HAMLET.
+Marry, this is miching mallecho; it means mischief.
+
+OPHELIA.
+Belike this show imports the argument of the play.
+
+Enter Prologue.
+
+HAMLET.
+We shall know by this fellow: the players cannot keep counsel; they’ll
+tell all.
+
+OPHELIA.
+Will they tell us what this show meant?
+
+HAMLET.
+Ay, or any show that you’ll show him. Be not you ashamed to show, he’ll
+not shame to tell you what it means.
+
+OPHELIA.
+You are naught, you are naught: I’ll mark the play.
+
+PROLOGUE.
+   _For us, and for our tragedy,
+   Here stooping to your clemency,
+   We beg your hearing patiently._
+
+HAMLET.
+Is this a prologue, or the posy of a ring?
+
+OPHELIA.
+’Tis brief, my lord.
+
+HAMLET.
+As woman’s love.
+
+Enter a King and a Queen.
+
+PLAYER KING.
+Full thirty times hath Phoebus’ cart gone round
+Neptune’s salt wash and Tellus’ orbed ground,
+And thirty dozen moons with borrow’d sheen
+About the world have times twelve thirties been,
+Since love our hearts, and Hymen did our hands
+Unite commutual in most sacred bands.
+
+PLAYER QUEEN.
+So many journeys may the sun and moon
+Make us again count o’er ere love be done.
+But, woe is me, you are so sick of late,
+So far from cheer and from your former state,
+That I distrust you. Yet, though I distrust,
+Discomfort you, my lord, it nothing must:
+For women’s fear and love holds quantity,
+In neither aught, or in extremity.
+Now what my love is, proof hath made you know,
+And as my love is siz’d, my fear is so.
+Where love is great, the littlest doubts are fear;
+Where little fears grow great, great love grows there.
+
+PLAYER KING.
+Faith, I must leave thee, love, and shortly too:
+My operant powers their functions leave to do:
+And thou shalt live in this fair world behind,
+Honour’d, belov’d, and haply one as kind
+For husband shalt thou—
+
+PLAYER QUEEN.
+O confound the rest.
+Such love must needs be treason in my breast.
+In second husband let me be accurst!
+None wed the second but who kill’d the first.
+
+HAMLET.
+[_Aside._] Wormwood, wormwood.
+
+PLAYER QUEEN.
+The instances that second marriage move
+Are base respects of thrift, but none of love.
+A second time I kill my husband dead,
+When second husband kisses me in bed.
+
+PLAYER KING.
+I do believe you think what now you speak;
+But what we do determine, oft we break.
+Purpose is but the slave to memory,
+Of violent birth, but poor validity:
+Which now, like fruit unripe, sticks on the tree,
+But fall unshaken when they mellow be.
+Most necessary ’tis that we forget
+To pay ourselves what to ourselves is debt.
+What to ourselves in passion we propose,
+The passion ending, doth the purpose lose.
+The violence of either grief or joy
+Their own enactures with themselves destroy.
+Where joy most revels, grief doth most lament;
+Grief joys, joy grieves, on slender accident.
+This world is not for aye; nor ’tis not strange
+That even our loves should with our fortunes change,
+For ’tis a question left us yet to prove,
+Whether love lead fortune, or else fortune love.
+The great man down, you mark his favourite flies,
+The poor advanc’d makes friends of enemies;
+And hitherto doth love on fortune tend:
+For who not needs shall never lack a friend,
+And who in want a hollow friend doth try,
+Directly seasons him his enemy.
+But orderly to end where I begun,
+Our wills and fates do so contrary run
+That our devices still are overthrown.
+Our thoughts are ours, their ends none of our own.
+So think thou wilt no second husband wed,
+But die thy thoughts when thy first lord is dead.
+
+PLAYER QUEEN.
+Nor earth to me give food, nor heaven light,
+Sport and repose lock from me day and night,
+To desperation turn my trust and hope,
+An anchor’s cheer in prison be my scope,
+Each opposite that blanks the face of joy,
+Meet what I would have well, and it destroy!
+Both here and hence pursue me lasting strife,
+If, once a widow, ever I be wife.
+
+HAMLET.
+[_To Ophelia._] If she should break it now.
+
+PLAYER KING.
+’Tis deeply sworn. Sweet, leave me here awhile.
+My spirits grow dull, and fain I would beguile
+The tedious day with sleep.
+[_Sleeps._]
+
+PLAYER QUEEN.
+Sleep rock thy brain,
+And never come mischance between us twain.
+
+[_Exit._]
+
+HAMLET.
+Madam, how like you this play?
+
+QUEEN.
+The lady protests too much, methinks.
+
+HAMLET.
+O, but she’ll keep her word.
+
+KING.
+Have you heard the argument? Is there no offence in’t?
+
+HAMLET.
+No, no, they do but jest, poison in jest; no offence i’ th’ world.
+
+KING.
+What do you call the play?
+
+HAMLET.
+_The Mousetrap._ Marry, how? Tropically. This play is the image of a
+murder done in Vienna. Gonzago is the Duke’s name, his wife Baptista:
+you shall see anon; ’tis a knavish piece of work: but what o’ that?
+Your majesty, and we that have free souls, it touches us not. Let the
+gall’d jade wince; our withers are unwrung.
+
+Enter Lucianus.
+
+This is one Lucianus, nephew to the King.
+
+OPHELIA.
+You are a good chorus, my lord.
+
+HAMLET.
+I could interpret between you and your love, if I could see the puppets
+dallying.
+
+OPHELIA.
+You are keen, my lord, you are keen.
+
+HAMLET.
+It would cost you a groaning to take off my edge.
+
+OPHELIA.
+Still better, and worse.
+
+HAMLET.
+So you mistake your husbands.—Begin, murderer. Pox, leave thy damnable
+faces, and begin. Come, the croaking raven doth bellow for revenge.
+
+LUCIANUS.
+Thoughts black, hands apt, drugs fit, and time agreeing,
+Confederate season, else no creature seeing;
+Thou mixture rank, of midnight weeds collected,
+With Hecate’s ban thrice blasted, thrice infected,
+Thy natural magic and dire property
+On wholesome life usurp immediately.
+
+[_Pours the poison into the sleeper’s ears._]
+
+HAMLET.
+He poisons him i’ th’garden for’s estate. His name’s Gonzago. The story
+is extant, and written in very choice Italian. You shall see anon how
+the murderer gets the love of Gonzago’s wife.
+
+OPHELIA.
+The King rises.
+
+HAMLET.
+What, frighted with false fire?
+
+QUEEN.
+How fares my lord?
+
+POLONIUS.
+Give o’er the play.
+
+KING.
+Give me some light. Away.
+
+All.
+Lights, lights, lights.
+
+[_Exeunt all but Hamlet and Horatio._]
+
+HAMLET.
+   Why, let the strucken deer go weep,
+     The hart ungalled play;
+   For some must watch, while some must sleep,
+     So runs the world away.
+Would not this, sir, and a forest of feathers, if the rest of my
+fortunes turn Turk with me; with two Provincial roses on my razed
+shoes, get me a fellowship in a cry of players, sir?
+
+HORATIO.
+Half a share.
+
+HAMLET.
+A whole one, I.
+   For thou dost know, O Damon dear,
+     This realm dismantled was
+   Of Jove himself, and now reigns here
+     A very, very—pajock.
+
+HORATIO.
+You might have rhymed.
+
+HAMLET.
+O good Horatio, I’ll take the ghost’s word for a thousand pound. Didst
+perceive?
+
+HORATIO.
+Very well, my lord.
+
+HAMLET.
+Upon the talk of the poisoning?
+
+HORATIO.
+I did very well note him.
+
+HAMLET.
+Ah, ha! Come, some music. Come, the recorders.
+   For if the king like not the comedy,
+   Why then, belike he likes it not, perdie.
+Come, some music.
+
+Enter Rosencrantz and Guildenstern.
+
+GUILDENSTERN.
+Good my lord, vouchsafe me a word with you.
+
+HAMLET.
+Sir, a whole history.
+
+GUILDENSTERN.
+The King, sir—
+
+HAMLET.
+Ay, sir, what of him?
+
+GUILDENSTERN.
+Is in his retirement, marvellous distempered.
+
+HAMLET.
+With drink, sir?
+
+GUILDENSTERN.
+No, my lord; rather with choler.
+
+HAMLET.
+Your wisdom should show itself more richer to signify this to the
+doctor, for me to put him to his purgation would perhaps plunge him
+into far more choler.
+
+GUILDENSTERN.
+Good my lord, put your discourse into some frame, and start not so
+wildly from my affair.
+
+HAMLET.
+I am tame, sir, pronounce.
+
+GUILDENSTERN.
+The Queen your mother, in most great affliction of spirit, hath sent me
+to you.
+
+HAMLET.
+You are welcome.
+
+GUILDENSTERN.
+Nay, good my lord, this courtesy is not of the right breed. If it shall
+please you to make me a wholesome answer, I will do your mother’s
+commandment; if not, your pardon and my return shall be the end of my
+business.
+
+HAMLET.
+Sir, I cannot.
+
+GUILDENSTERN.
+What, my lord?
+
+HAMLET.
+Make you a wholesome answer. My wit’s diseased. But, sir, such answer
+as I can make, you shall command; or rather, as you say, my mother.
+Therefore no more, but to the matter. My mother, you say,—
+
+ROSENCRANTZ.
+Then thus she says: your behaviour hath struck her into amazement and
+admiration.
+
+HAMLET.
+O wonderful son, that can so stonish a mother! But is there no sequel
+at the heels of this mother’s admiration?
+
+ROSENCRANTZ.
+She desires to speak with you in her closet ere you go to bed.
+
+HAMLET.
+We shall obey, were she ten times our mother. Have you any further
+trade with us?
+
+ROSENCRANTZ.
+My lord, you once did love me.
+
+HAMLET.
+And so I do still, by these pickers and stealers.
+
+ROSENCRANTZ.
+Good my lord, what is your cause of distemper? You do surely bar the
+door upon your own liberty if you deny your griefs to your friend.
+
+HAMLET.
+Sir, I lack advancement.
+
+ROSENCRANTZ.
+How can that be, when you have the voice of the King himself for your
+succession in Denmark?
+
+HAMLET.
+Ay, sir, but while the grass grows—the proverb is something musty.
+
+Re-enter the Players with recorders.
+
+O, the recorders. Let me see one.—To withdraw with you, why do you go
+about to recover the wind of me, as if you would drive me into a toil?
+
+GUILDENSTERN.
+O my lord, if my duty be too bold, my love is too unmannerly.
+
+HAMLET.
+I do not well understand that. Will you play upon this pipe?
+
+GUILDENSTERN.
+My lord, I cannot.
+
+HAMLET.
+I pray you.
+
+GUILDENSTERN.
+Believe me, I cannot.
+
+HAMLET.
+I do beseech you.
+
+GUILDENSTERN.
+I know no touch of it, my lord.
+
+HAMLET.
+’Tis as easy as lying: govern these ventages with your finger and
+thumb, give it breath with your mouth, and it will discourse most
+eloquent music. Look you, these are the stops.
+
+GUILDENSTERN.
+But these cannot I command to any utterance of harmony. I have not the
+skill.
+
+HAMLET.
+Why, look you now, how unworthy a thing you make of me! You would play
+upon me; you would seem to know my stops; you would pluck out the heart
+of my mystery; you would sound me from my lowest note to the top of my
+compass; and there is much music, excellent voice, in this little
+organ, yet cannot you make it speak. ’Sblood, do you think I am easier
+to be played on than a pipe? Call me what instrument you will, though
+you can fret me, you cannot play upon me.
+
+Enter Polonius.
+
+God bless you, sir.
+
+POLONIUS.
+My lord, the Queen would speak with you, and presently.
+
+HAMLET.
+Do you see yonder cloud that’s almost in shape of a camel?
+
+POLONIUS.
+By the mass, and ’tis like a camel indeed.
+
+HAMLET.
+Methinks it is like a weasel.
+
+POLONIUS.
+It is backed like a weasel.
+
+HAMLET.
+Or like a whale.
+
+POLONIUS.
+Very like a whale.
+
+HAMLET.
+Then will I come to my mother by and by.—They fool me to the top of my
+bent.—I will come by and by.
+
+POLONIUS.
+I will say so.
+
+[_Exit._]
+
+HAMLET.
+By and by is easily said. Leave me, friends.
+
+[_Exeunt all but Hamlet._]
+
+’Tis now the very witching time of night,
+When churchyards yawn, and hell itself breathes out
+Contagion to this world. Now could I drink hot blood,
+And do such bitter business as the day
+Would quake to look on. Soft now, to my mother.
+O heart, lose not thy nature; let not ever
+The soul of Nero enter this firm bosom:
+Let me be cruel, not unnatural.
+I will speak daggers to her, but use none;
+My tongue and soul in this be hypocrites.
+How in my words somever she be shent,
+To give them seals never, my soul, consent.
+
+[_Exit._]
+
+ SCENE III. A room in the Castle.
+
+Enter King, Rosencrantz and Guildenstern.
+
+KING.
+I like him not, nor stands it safe with us
+To let his madness range. Therefore prepare you,
+I your commission will forthwith dispatch,
+And he to England shall along with you.
+The terms of our estate may not endure
+Hazard so near us as doth hourly grow
+Out of his lunacies.
+
+GUILDENSTERN.
+We will ourselves provide.
+Most holy and religious fear it is
+To keep those many many bodies safe
+That live and feed upon your Majesty.
+
+ROSENCRANTZ.
+The single and peculiar life is bound
+With all the strength and armour of the mind,
+To keep itself from ’noyance; but much more
+That spirit upon whose weal depend and rest
+The lives of many. The cease of majesty
+Dies not alone; but like a gulf doth draw
+What’s near it with it. It is a massy wheel
+Fix’d on the summit of the highest mount,
+To whose huge spokes ten thousand lesser things
+Are mortis’d and adjoin’d; which when it falls,
+Each small annexment, petty consequence,
+Attends the boist’rous ruin. Never alone
+Did the King sigh, but with a general groan.
+
+KING.
+Arm you, I pray you, to this speedy voyage;
+For we will fetters put upon this fear,
+Which now goes too free-footed.
+
+ROSENCRANTZ and GUILDENSTERN.
+We will haste us.
+
+[_Exeunt Rosencrantz and Guildenstern._]
+
+Enter Polonius.
+
+POLONIUS.
+My lord, he’s going to his mother’s closet.
+Behind the arras I’ll convey myself
+To hear the process. I’ll warrant she’ll tax him home,
+And as you said, and wisely was it said,
+’Tis meet that some more audience than a mother,
+Since nature makes them partial, should o’erhear
+The speech of vantage. Fare you well, my liege,
+I’ll call upon you ere you go to bed,
+And tell you what I know.
+
+KING.
+Thanks, dear my lord.
+
+[_Exit Polonius._]
+
+O, my offence is rank, it smells to heaven;
+It hath the primal eldest curse upon’t,—
+A brother’s murder! Pray can I not,
+Though inclination be as sharp as will:
+My stronger guilt defeats my strong intent,
+And, like a man to double business bound,
+I stand in pause where I shall first begin,
+And both neglect. What if this cursed hand
+Were thicker than itself with brother’s blood,
+Is there not rain enough in the sweet heavens
+To wash it white as snow? Whereto serves mercy
+But to confront the visage of offence?
+And what’s in prayer but this twofold force,
+To be forestalled ere we come to fall,
+Or pardon’d being down? Then I’ll look up.
+My fault is past. But O, what form of prayer
+Can serve my turn? Forgive me my foul murder!
+That cannot be; since I am still possess’d
+Of those effects for which I did the murder,—
+My crown, mine own ambition, and my queen.
+May one be pardon’d and retain th’offence?
+In the corrupted currents of this world
+Offence’s gilded hand may shove by justice,
+And oft ’tis seen the wicked prize itself
+Buys out the law. But ’tis not so above;
+There is no shuffling, there the action lies
+In his true nature, and we ourselves compell’d
+Even to the teeth and forehead of our faults,
+To give in evidence. What then? What rests?
+Try what repentance can. What can it not?
+Yet what can it, when one cannot repent?
+O wretched state! O bosom black as death!
+O limed soul, that struggling to be free,
+Art more engag’d! Help, angels! Make assay:
+Bow, stubborn knees; and heart with strings of steel,
+Be soft as sinews of the new-born babe.
+All may be well.
+
+[_Retires and kneels._]
+
+Enter Hamlet.
+
+HAMLET.
+Now might I do it pat, now he is praying.
+And now I’ll do’t. And so he goes to heaven;
+And so am I reveng’d. That would be scann’d:
+A villain kills my father, and for that
+I, his sole son, do this same villain send
+To heaven. O, this is hire and salary, not revenge.
+He took my father grossly, full of bread,
+With all his crimes broad blown, as flush as May;
+And how his audit stands, who knows save heaven?
+But in our circumstance and course of thought,
+’Tis heavy with him. And am I then reveng’d,
+To take him in the purging of his soul,
+When he is fit and season’d for his passage? No.
+Up, sword, and know thou a more horrid hent:
+When he is drunk asleep; or in his rage,
+Or in th’incestuous pleasure of his bed,
+At gaming, swearing; or about some act
+That has no relish of salvation in’t,
+Then trip him, that his heels may kick at heaven,
+And that his soul may be as damn’d and black
+As hell, whereto it goes. My mother stays.
+This physic but prolongs thy sickly days.
+
+[_Exit._]
+
+The King rises and advances.
+
+KING.
+My words fly up, my thoughts remain below.
+Words without thoughts never to heaven go.
+
+[_Exit._]
+
+ SCENE IV. Another room in the Castle.
+
+Enter Queen and Polonius.
+
+POLONIUS.
+He will come straight. Look you lay home to him,
+Tell him his pranks have been too broad to bear with,
+And that your Grace hath screen’d and stood between
+Much heat and him. I’ll silence me e’en here.
+Pray you be round with him.
+
+HAMLET.
+[_Within._] Mother, mother, mother.
+
+QUEEN.
+I’ll warrant you, Fear me not.
+Withdraw, I hear him coming.
+
+[_Polonius goes behind the arras._]
+
+Enter Hamlet.
+
+HAMLET.
+Now, mother, what’s the matter?
+
+QUEEN.
+Hamlet, thou hast thy father much offended.
+
+HAMLET.
+Mother, you have my father much offended.
+
+QUEEN.
+Come, come, you answer with an idle tongue.
+
+HAMLET.
+Go, go, you question with a wicked tongue.
+
+QUEEN.
+Why, how now, Hamlet?
+
+HAMLET.
+What’s the matter now?
+
+QUEEN.
+Have you forgot me?
+
+HAMLET.
+No, by the rood, not so.
+You are the Queen, your husband’s brother’s wife,
+And, would it were not so. You are my mother.
+
+QUEEN.
+Nay, then I’ll set those to you that can speak.
+
+HAMLET.
+Come, come, and sit you down, you shall not budge.
+You go not till I set you up a glass
+Where you may see the inmost part of you.
+
+QUEEN.
+What wilt thou do? Thou wilt not murder me?
+Help, help, ho!
+
+POLONIUS.
+[_Behind._] What, ho! help, help, help!
+
+HAMLET.
+How now? A rat? [_Draws._]
+Dead for a ducat, dead!
+
+[_Makes a pass through the arras._]
+
+POLONIUS.
+[_Behind._] O, I am slain!
+
+[_Falls and dies._]
+
+QUEEN.
+O me, what hast thou done?
+
+HAMLET.
+Nay, I know not. Is it the King?
+
+[_Draws forth Polonius._]
+
+QUEEN.
+O what a rash and bloody deed is this!
+
+HAMLET.
+A bloody deed. Almost as bad, good mother,
+As kill a king and marry with his brother.
+
+QUEEN.
+As kill a king?
+
+HAMLET.
+Ay, lady, ’twas my word.—
+[_To Polonius._] Thou wretched, rash, intruding fool, farewell!
+I took thee for thy better. Take thy fortune,
+Thou find’st to be too busy is some danger.—
+Leave wringing of your hands. Peace, sit you down,
+And let me wring your heart, for so I shall,
+If it be made of penetrable stuff;
+If damned custom have not braz’d it so,
+That it is proof and bulwark against sense.
+
+QUEEN.
+What have I done, that thou dar’st wag thy tongue
+In noise so rude against me?
+
+HAMLET.
+Such an act
+That blurs the grace and blush of modesty,
+Calls virtue hypocrite, takes off the rose
+From the fair forehead of an innocent love,
+And sets a blister there. Makes marriage vows
+As false as dicers’ oaths. O such a deed
+As from the body of contraction plucks
+The very soul, and sweet religion makes
+A rhapsody of words. Heaven’s face doth glow,
+Yea this solidity and compound mass,
+With tristful visage, as against the doom,
+Is thought-sick at the act.
+
+QUEEN.
+Ay me, what act,
+That roars so loud, and thunders in the index?
+
+HAMLET.
+Look here upon this picture, and on this,
+The counterfeit presentment of two brothers.
+See what a grace was seated on this brow,
+Hyperion’s curls, the front of Jove himself,
+An eye like Mars, to threaten and command,
+A station like the herald Mercury
+New lighted on a heaven-kissing hill:
+A combination and a form indeed,
+Where every god did seem to set his seal,
+To give the world assurance of a man.
+This was your husband. Look you now what follows.
+Here is your husband, like a mildew’d ear
+Blasting his wholesome brother. Have you eyes?
+Could you on this fair mountain leave to feed,
+And batten on this moor? Ha! have you eyes?
+You cannot call it love; for at your age
+The hey-day in the blood is tame, it’s humble,
+And waits upon the judgement: and what judgement
+Would step from this to this? Sense sure you have,
+Else could you not have motion; but sure that sense
+Is apoplex’d, for madness would not err
+Nor sense to ecstacy was ne’er so thrall’d
+But it reserv’d some quantity of choice
+To serve in such a difference. What devil was’t
+That thus hath cozen’d you at hoodman-blind?
+Eyes without feeling, feeling without sight,
+Ears without hands or eyes, smelling sans all,
+Or but a sickly part of one true sense
+Could not so mope. O shame! where is thy blush?
+Rebellious hell,
+If thou canst mutine in a matron’s bones,
+To flaming youth let virtue be as wax,
+And melt in her own fire. Proclaim no shame
+When the compulsive ardour gives the charge,
+Since frost itself as actively doth burn,
+And reason panders will.
+
+QUEEN.
+O Hamlet, speak no more.
+Thou turn’st mine eyes into my very soul,
+And there I see such black and grained spots
+As will not leave their tinct.
+
+HAMLET.
+Nay, but to live
+In the rank sweat of an enseamed bed,
+Stew’d in corruption, honeying and making love
+Over the nasty sty.
+
+QUEEN.
+O speak to me no more;
+These words like daggers enter in mine ears;
+No more, sweet Hamlet.
+
+HAMLET.
+A murderer and a villain;
+A slave that is not twentieth part the tithe
+Of your precedent lord. A vice of kings,
+A cutpurse of the empire and the rule,
+That from a shelf the precious diadem stole
+And put it in his pocket!
+
+QUEEN.
+No more.
+
+HAMLET.
+A king of shreds and patches!—
+
+Enter Ghost.
+
+Save me and hover o’er me with your wings,
+You heavenly guards! What would your gracious figure?
+
+QUEEN.
+Alas, he’s mad.
+
+HAMLET.
+Do you not come your tardy son to chide,
+That, laps’d in time and passion, lets go by
+The important acting of your dread command?
+O say!
+
+GHOST.
+Do not forget. This visitation
+Is but to whet thy almost blunted purpose.
+But look, amazement on thy mother sits.
+O step between her and her fighting soul.
+Conceit in weakest bodies strongest works.
+Speak to her, Hamlet.
+
+HAMLET.
+How is it with you, lady?
+
+QUEEN.
+Alas, how is’t with you,
+That you do bend your eye on vacancy,
+And with the incorporal air do hold discourse?
+Forth at your eyes your spirits wildly peep,
+And, as the sleeping soldiers in the alarm,
+Your bedded hairs, like life in excrements,
+Start up and stand an end. O gentle son,
+Upon the heat and flame of thy distemper
+Sprinkle cool patience. Whereon do you look?
+
+HAMLET.
+On him, on him! Look you how pale he glares,
+His form and cause conjoin’d, preaching to stones,
+Would make them capable.—Do not look upon me,
+Lest with this piteous action you convert
+My stern effects. Then what I have to do
+Will want true colour; tears perchance for blood.
+
+QUEEN.
+To whom do you speak this?
+
+HAMLET.
+Do you see nothing there?
+
+QUEEN.
+Nothing at all; yet all that is I see.
+
+HAMLET.
+Nor did you nothing hear?
+
+QUEEN.
+No, nothing but ourselves.
+
+HAMLET.
+Why, look you there! look how it steals away!
+My father, in his habit as he liv’d!
+Look where he goes even now out at the portal.
+
+[_Exit Ghost._]
+
+QUEEN.
+This is the very coinage of your brain.
+This bodiless creation ecstasy
+Is very cunning in.
+
+HAMLET.
+Ecstasy!
+My pulse as yours doth temperately keep time,
+And makes as healthful music. It is not madness
+That I have utter’d. Bring me to the test,
+And I the matter will re-word; which madness
+Would gambol from. Mother, for love of grace,
+Lay not that flattering unction to your soul
+That not your trespass, but my madness speaks.
+It will but skin and film the ulcerous place,
+Whilst rank corruption, mining all within,
+Infects unseen. Confess yourself to heaven,
+Repent what’s past, avoid what is to come;
+And do not spread the compost on the weeds,
+To make them ranker. Forgive me this my virtue;
+For in the fatness of these pursy times
+Virtue itself of vice must pardon beg,
+Yea, curb and woo for leave to do him good.
+
+QUEEN.
+O Hamlet, thou hast cleft my heart in twain.
+
+HAMLET.
+O throw away the worser part of it,
+And live the purer with the other half.
+Good night. But go not to mine uncle’s bed.
+Assume a virtue, if you have it not.
+That monster custom, who all sense doth eat,
+Of habits evil, is angel yet in this,
+That to the use of actions fair and good
+He likewise gives a frock or livery
+That aptly is put on. Refrain tonight,
+And that shall lend a kind of easiness
+To the next abstinence. The next more easy;
+For use almost can change the stamp of nature,
+And either curb the devil, or throw him out
+With wondrous potency. Once more, good night,
+And when you are desirous to be bles’d,
+I’ll blessing beg of you. For this same lord
+[_Pointing to Polonius._]
+I do repent; but heaven hath pleas’d it so,
+To punish me with this, and this with me,
+That I must be their scourge and minister.
+I will bestow him, and will answer well
+The death I gave him. So again, good night.
+I must be cruel, only to be kind:
+Thus bad begins, and worse remains behind.
+One word more, good lady.
+
+QUEEN.
+What shall I do?
+
+HAMLET.
+Not this, by no means, that I bid you do:
+Let the bloat King tempt you again to bed,
+Pinch wanton on your cheek, call you his mouse,
+And let him, for a pair of reechy kisses,
+Or paddling in your neck with his damn’d fingers,
+Make you to ravel all this matter out,
+That I essentially am not in madness,
+But mad in craft. ’Twere good you let him know,
+For who that’s but a queen, fair, sober, wise,
+Would from a paddock, from a bat, a gib,
+Such dear concernings hide? Who would do so?
+No, in despite of sense and secrecy,
+Unpeg the basket on the house’s top,
+Let the birds fly, and like the famous ape,
+To try conclusions, in the basket creep
+And break your own neck down.
+
+QUEEN.
+Be thou assur’d, if words be made of breath,
+And breath of life, I have no life to breathe
+What thou hast said to me.
+
+HAMLET.
+I must to England, you know that?
+
+QUEEN.
+Alack,
+I had forgot. ’Tis so concluded on.
+
+HAMLET.
+There’s letters seal’d: and my two schoolfellows,
+Whom I will trust as I will adders fang’d,—
+They bear the mandate, they must sweep my way
+And marshal me to knavery. Let it work;
+For ’tis the sport to have the enginer
+Hoist with his own petard, and ’t shall go hard
+But I will delve one yard below their mines
+And blow them at the moon. O, ’tis most sweet,
+When in one line two crafts directly meet.
+This man shall set me packing.
+I’ll lug the guts into the neighbour room.
+Mother, good night. Indeed, this counsellor
+Is now most still, most secret, and most grave,
+Who was in life a foolish prating knave.
+Come, sir, to draw toward an end with you.
+Good night, mother.
+
+[_Exit Hamlet dragging out Polonius._]
+
+
+
+
+ACT IV
+
+SCENE I. A room in the Castle.
+
+
+Enter King, Queen, Rosencrantz and Guildenstern.
+
+KING.
+There’s matter in these sighs. These profound heaves
+You must translate; ’tis fit we understand them.
+Where is your son?
+
+QUEEN.
+Bestow this place on us a little while.
+
+[_To Rosencrantz and Guildenstern, who go out._]
+
+Ah, my good lord, what have I seen tonight!
+
+KING.
+What, Gertrude? How does Hamlet?
+
+QUEEN.
+Mad as the sea and wind, when both contend
+Which is the mightier. In his lawless fit
+Behind the arras hearing something stir,
+Whips out his rapier, cries ‘A rat, a rat!’
+And in this brainish apprehension kills
+The unseen good old man.
+
+KING.
+O heavy deed!
+It had been so with us, had we been there.
+His liberty is full of threats to all;
+To you yourself, to us, to everyone.
+Alas, how shall this bloody deed be answer’d?
+It will be laid to us, whose providence
+Should have kept short, restrain’d, and out of haunt
+This mad young man. But so much was our love
+We would not understand what was most fit,
+But like the owner of a foul disease,
+To keep it from divulging, let it feed
+Even on the pith of life. Where is he gone?
+
+QUEEN.
+To draw apart the body he hath kill’d,
+O’er whom his very madness, like some ore
+Among a mineral of metals base,
+Shows itself pure. He weeps for what is done.
+
+KING.
+O Gertrude, come away!
+The sun no sooner shall the mountains touch
+But we will ship him hence, and this vile deed
+We must with all our majesty and skill
+Both countenance and excuse.—Ho, Guildenstern!
+
+Re-enter Rosencrantz and Guildenstern.
+
+Friends both, go join you with some further aid:
+Hamlet in madness hath Polonius slain,
+And from his mother’s closet hath he dragg’d him.
+Go seek him out, speak fair, and bring the body
+Into the chapel. I pray you haste in this.
+
+[_Exeunt Rosencrantz and Guildenstern._]
+
+Come, Gertrude, we’ll call up our wisest friends,
+And let them know both what we mean to do
+And what’s untimely done, so haply slander,
+Whose whisper o’er the world’s diameter,
+As level as the cannon to his blank,
+Transports his poison’d shot, may miss our name,
+And hit the woundless air. O, come away!
+My soul is full of discord and dismay.
+
+[_Exeunt._]
+
+ SCENE II. Another room in the Castle.
+
+Enter Hamlet.
+
+HAMLET.
+Safely stowed.
+
+ROSENCRANTZ and GUILDENSTERN.
+[_Within._] Hamlet! Lord Hamlet!
+
+HAMLET.
+What noise? Who calls on Hamlet? O, here they come.
+
+Enter Rosencrantz and Guildenstern.
+
+ROSENCRANTZ.
+What have you done, my lord, with the dead body?
+
+HAMLET.
+Compounded it with dust, whereto ’tis kin.
+
+ROSENCRANTZ.
+Tell us where ’tis, that we may take it thence,
+And bear it to the chapel.
+
+HAMLET.
+Do not believe it.
+
+ROSENCRANTZ.
+Believe what?
+
+HAMLET.
+That I can keep your counsel, and not mine own. Besides, to be demanded
+of a sponge—what replication should be made by the son of a king?
+
+ROSENCRANTZ.
+Take you me for a sponge, my lord?
+
+HAMLET.
+Ay, sir; that soaks up the King’s countenance, his rewards, his
+authorities. But such officers do the King best service in the end: he
+keeps them, like an ape, in the corner of his jaw; first mouthed, to be
+last swallowed: when he needs what you have gleaned, it is but
+squeezing you, and, sponge, you shall be dry again.
+
+ROSENCRANTZ.
+I understand you not, my lord.
+
+HAMLET.
+I am glad of it. A knavish speech sleeps in a foolish ear.
+
+ROSENCRANTZ.
+My lord, you must tell us where the body is and go with us to the King.
+
+HAMLET.
+The body is with the King, but the King is not with the body. The King
+is a thing—
+
+GUILDENSTERN.
+A thing, my lord!
+
+HAMLET.
+Of nothing. Bring me to him. Hide fox, and all after.
+
+[_Exeunt._]
+
+ SCENE III. Another room in the Castle.
+
+Enter King, attended.
+
+KING.
+I have sent to seek him and to find the body.
+How dangerous is it that this man goes loose!
+Yet must not we put the strong law on him:
+He’s lov’d of the distracted multitude,
+Who like not in their judgement, but their eyes;
+And where ’tis so, th’offender’s scourge is weigh’d,
+But never the offence. To bear all smooth and even,
+This sudden sending him away must seem
+Deliberate pause. Diseases desperate grown
+By desperate appliance are reliev’d,
+Or not at all.
+
+Enter Rosencrantz.
+
+How now? What hath befall’n?
+
+ROSENCRANTZ.
+Where the dead body is bestow’d, my lord,
+We cannot get from him.
+
+KING.
+But where is he?
+
+ROSENCRANTZ.
+Without, my lord, guarded, to know your pleasure.
+
+KING.
+Bring him before us.
+
+ROSENCRANTZ.
+Ho, Guildenstern! Bring in my lord.
+
+Enter Hamlet and Guildenstern.
+
+KING.
+Now, Hamlet, where’s Polonius?
+
+HAMLET.
+At supper.
+
+KING.
+At supper? Where?
+
+HAMLET.
+Not where he eats, but where he is eaten. A certain convocation of
+politic worms are e’en at him. Your worm is your only emperor for diet.
+We fat all creatures else to fat us, and we fat ourselves for maggots.
+Your fat king and your lean beggar is but variable service,—two dishes,
+but to one table. That’s the end.
+
+KING.
+Alas, alas!
+
+HAMLET.
+A man may fish with the worm that hath eat of a king, and eat of the
+fish that hath fed of that worm.
+
+KING.
+What dost thou mean by this?
+
+HAMLET.
+Nothing but to show you how a king may go a progress through the guts
+of a beggar.
+
+KING.
+Where is Polonius?
+
+HAMLET.
+In heaven. Send thither to see. If your messenger find him not there,
+seek him i’ th’other place yourself. But indeed, if you find him not
+within this month, you shall nose him as you go up the stairs into the
+lobby.
+
+KING.
+[_To some Attendants._] Go seek him there.
+
+HAMLET.
+He will stay till you come.
+
+[_Exeunt Attendants._]
+
+KING.
+Hamlet, this deed, for thine especial safety,—
+Which we do tender, as we dearly grieve
+For that which thou hast done,—must send thee hence
+With fiery quickness. Therefore prepare thyself;
+The bark is ready, and the wind at help,
+Th’associates tend, and everything is bent
+For England.
+
+HAMLET.
+For England?
+
+KING.
+Ay, Hamlet.
+
+HAMLET.
+Good.
+
+KING.
+So is it, if thou knew’st our purposes.
+
+HAMLET.
+I see a cherub that sees them. But, come; for England! Farewell, dear
+mother.
+
+KING.
+Thy loving father, Hamlet.
+
+HAMLET.
+My mother. Father and mother is man and wife; man and wife is one
+flesh; and so, my mother. Come, for England.
+
+[_Exit._]
+
+KING.
+Follow him at foot. Tempt him with speed aboard;
+Delay it not; I’ll have him hence tonight.
+Away, for everything is seal’d and done
+That else leans on th’affair. Pray you make haste.
+
+[_Exeunt Rosencrantz and Guildenstern._]
+
+And England, if my love thou hold’st at aught,—
+As my great power thereof may give thee sense,
+Since yet thy cicatrice looks raw and red
+After the Danish sword, and thy free awe
+Pays homage to us,—thou mayst not coldly set
+Our sovereign process, which imports at full,
+By letters conjuring to that effect,
+The present death of Hamlet. Do it, England;
+For like the hectic in my blood he rages,
+And thou must cure me. Till I know ’tis done,
+Howe’er my haps, my joys were ne’er begun.
+
+[_Exit._]
+
+ SCENE IV. A plain in Denmark.
+
+Enter Fortinbras and Forces marching.
+
+FORTINBRAS.
+Go, Captain, from me greet the Danish king.
+Tell him that by his license, Fortinbras
+Craves the conveyance of a promis’d march
+Over his kingdom. You know the rendezvous.
+If that his Majesty would aught with us,
+We shall express our duty in his eye;
+And let him know so.
+
+CAPTAIN.
+I will do’t, my lord.
+
+FORTINBRAS.
+Go softly on.
+
+[_Exeunt all but the Captain._]
+
+Enter Hamlet, Rosencrantz, Guildenstern &c.
+
+HAMLET.
+Good sir, whose powers are these?
+
+CAPTAIN.
+They are of Norway, sir.
+
+HAMLET.
+How purpos’d, sir, I pray you?
+
+CAPTAIN.
+Against some part of Poland.
+
+HAMLET.
+Who commands them, sir?
+
+CAPTAIN.
+The nephew to old Norway, Fortinbras.
+
+HAMLET.
+Goes it against the main of Poland, sir,
+Or for some frontier?
+
+CAPTAIN.
+Truly to speak, and with no addition,
+We go to gain a little patch of ground
+That hath in it no profit but the name.
+To pay five ducats, five, I would not farm it;
+Nor will it yield to Norway or the Pole
+A ranker rate, should it be sold in fee.
+
+HAMLET.
+Why, then the Polack never will defend it.
+
+CAPTAIN.
+Yes, it is already garrison’d.
+
+HAMLET.
+Two thousand souls and twenty thousand ducats
+Will not debate the question of this straw!
+This is th’imposthume of much wealth and peace,
+That inward breaks, and shows no cause without
+Why the man dies. I humbly thank you, sir.
+
+CAPTAIN.
+God b’ wi’ you, sir.
+
+[_Exit._]
+
+ROSENCRANTZ.
+Will’t please you go, my lord?
+
+HAMLET.
+I’ll be with you straight. Go a little before.
+
+[_Exeunt all but Hamlet._]
+
+How all occasions do inform against me,
+And spur my dull revenge. What is a man
+If his chief good and market of his time
+Be but to sleep and feed? A beast, no more.
+Sure he that made us with such large discourse,
+Looking before and after, gave us not
+That capability and godlike reason
+To fust in us unus’d. Now whether it be
+Bestial oblivion, or some craven scruple
+Of thinking too precisely on th’event,—
+A thought which, quarter’d, hath but one part wisdom
+And ever three parts coward,—I do not know
+Why yet I live to say this thing’s to do,
+Sith I have cause, and will, and strength, and means
+To do’t. Examples gross as earth exhort me,
+Witness this army of such mass and charge,
+Led by a delicate and tender prince,
+Whose spirit, with divine ambition puff’d,
+Makes mouths at the invisible event,
+Exposing what is mortal and unsure
+To all that fortune, death, and danger dare,
+Even for an eggshell. Rightly to be great
+Is not to stir without great argument,
+But greatly to find quarrel in a straw
+When honour’s at the stake. How stand I then,
+That have a father kill’d, a mother stain’d,
+Excitements of my reason and my blood,
+And let all sleep, while to my shame I see
+The imminent death of twenty thousand men
+That, for a fantasy and trick of fame,
+Go to their graves like beds, fight for a plot
+Whereon the numbers cannot try the cause,
+Which is not tomb enough and continent
+To hide the slain? O, from this time forth,
+My thoughts be bloody or be nothing worth.
+
+[_Exit._]
+
+ SCENE V. Elsinore. A room in the Castle.
+
+Enter Queen, Horatio and a Gentleman.
+
+QUEEN.
+I will not speak with her.
+
+GENTLEMAN.
+She is importunate, indeed distract.
+Her mood will needs be pitied.
+
+QUEEN.
+What would she have?
+
+GENTLEMAN.
+She speaks much of her father; says she hears
+There’s tricks i’ th’ world, and hems, and beats her heart,
+Spurns enviously at straws, speaks things in doubt,
+That carry but half sense. Her speech is nothing,
+Yet the unshaped use of it doth move
+The hearers to collection; they aim at it,
+And botch the words up fit to their own thoughts,
+Which, as her winks, and nods, and gestures yield them,
+Indeed would make one think there might be thought,
+Though nothing sure, yet much unhappily.
+’Twere good she were spoken with, for she may strew
+Dangerous conjectures in ill-breeding minds.
+
+QUEEN.
+Let her come in.
+
+[_Exit Gentleman._]
+
+To my sick soul, as sin’s true nature is,
+Each toy seems prologue to some great amiss.
+So full of artless jealousy is guilt,
+It spills itself in fearing to be spilt.
+
+Enter Ophelia.
+
+OPHELIA.
+Where is the beauteous Majesty of Denmark?
+
+QUEEN.
+How now, Ophelia?
+
+OPHELIA.
+[_Sings._]
+   How should I your true love know
+     From another one?
+   By his cockle hat and staff
+     And his sandal shoon.
+
+QUEEN.
+Alas, sweet lady, what imports this song?
+
+OPHELIA.
+Say you? Nay, pray you mark.
+[_Sings._]
+   He is dead and gone, lady,
+     He is dead and gone,
+   At his head a grass green turf,
+     At his heels a stone.
+
+QUEEN.
+Nay, but Ophelia—
+
+OPHELIA.
+Pray you mark.
+[_Sings._]
+   White his shroud as the mountain snow.
+
+Enter King.
+
+QUEEN.
+Alas, look here, my lord!
+
+OPHELIA.
+[_Sings._]
+     Larded all with sweet flowers;
+   Which bewept to the grave did not go
+     With true-love showers.
+
+KING.
+How do you, pretty lady?
+
+OPHELIA.
+Well, God dild you! They say the owl was a baker’s daughter. Lord, we
+know what we are, but know not what we may be. God be at your table!
+
+KING.
+Conceit upon her father.
+
+OPHELIA.
+Pray you, let’s have no words of this; but when they ask you what it
+means, say you this:
+[_Sings._]
+   Tomorrow is Saint Valentine’s day,
+     All in the morning betime,
+   And I a maid at your window,
+     To be your Valentine.
+
+   Then up he rose and donn’d his clothes,
+     And dupp’d the chamber door,
+   Let in the maid, that out a maid
+     Never departed more.
+
+KING.
+Pretty Ophelia!
+
+OPHELIA.
+Indeed la, without an oath, I’ll make an end on’t.
+[_Sings._]
+   By Gis and by Saint Charity,
+     Alack, and fie for shame!
+   Young men will do’t if they come to’t;
+     By Cock, they are to blame.
+
+   Quoth she, before you tumbled me,
+     You promis’d me to wed.
+   So would I ha’ done, by yonder sun,
+     An thou hadst not come to my bed.
+
+KING.
+How long hath she been thus?
+
+OPHELIA.
+I hope all will be well. We must be patient. But I cannot choose but
+weep, to think they would lay him i’ th’ cold ground. My brother shall
+know of it. And so I thank you for your good counsel. Come, my coach!
+Good night, ladies; good night, sweet ladies; good night, good night.
+
+[_Exit._]
+
+KING.
+Follow her close; give her good watch, I pray you.
+
+[_Exit Horatio._]
+
+O, this is the poison of deep grief; it springs
+All from her father’s death. O Gertrude, Gertrude,
+When sorrows come, they come not single spies,
+But in battalions. First, her father slain;
+Next, your son gone; and he most violent author
+Of his own just remove; the people muddied,
+Thick, and unwholesome in their thoughts and whispers
+For good Polonius’ death; and we have done but greenly
+In hugger-mugger to inter him. Poor Ophelia
+Divided from herself and her fair judgement,
+Without the which we are pictures or mere beasts.
+Last, and as much containing as all these,
+Her brother is in secret come from France,
+Feeds on his wonder, keeps himself in clouds,
+And wants not buzzers to infect his ear
+With pestilent speeches of his father’s death,
+Wherein necessity, of matter beggar’d,
+Will nothing stick our person to arraign
+In ear and ear. O my dear Gertrude, this,
+Like to a murdering piece, in many places
+Gives me superfluous death.
+
+[_A noise within._]
+
+QUEEN.
+Alack, what noise is this?
+
+KING.
+Where are my Switzers? Let them guard the door.
+
+Enter a Gentleman.
+
+What is the matter?
+
+GENTLEMAN.
+Save yourself, my lord.
+The ocean, overpeering of his list,
+Eats not the flats with more impetuous haste
+Than young Laertes, in a riotous head,
+O’erbears your offices. The rabble call him lord,
+And, as the world were now but to begin,
+Antiquity forgot, custom not known,
+The ratifiers and props of every word,
+They cry ‘Choose we! Laertes shall be king!’
+Caps, hands, and tongues applaud it to the clouds,
+‘Laertes shall be king, Laertes king.’
+
+QUEEN.
+How cheerfully on the false trail they cry.
+O, this is counter, you false Danish dogs.
+
+[_A noise within._]
+
+KING.
+The doors are broke.
+
+Enter Laertes, armed; Danes following.
+
+LAERTES.
+Where is this king?—Sirs, stand you all without.
+
+Danes.
+No, let’s come in.
+
+LAERTES.
+I pray you, give me leave.
+
+DANES.
+We will, we will.
+
+[_They retire without the door._]
+
+LAERTES.
+I thank you. Keep the door. O thou vile king,
+Give me my father.
+
+QUEEN.
+Calmly, good Laertes.
+
+LAERTES.
+That drop of blood that’s calm proclaims me bastard;
+Cries cuckold to my father, brands the harlot
+Even here between the chaste unsmirched brow
+Of my true mother.
+
+KING.
+What is the cause, Laertes,
+That thy rebellion looks so giant-like?—
+Let him go, Gertrude. Do not fear our person.
+There’s such divinity doth hedge a king,
+That treason can but peep to what it would,
+Acts little of his will.—Tell me, Laertes,
+Why thou art thus incens’d.—Let him go, Gertrude:—
+Speak, man.
+
+LAERTES.
+Where is my father?
+
+KING.
+Dead.
+
+QUEEN.
+But not by him.
+
+KING.
+Let him demand his fill.
+
+LAERTES.
+How came he dead? I’ll not be juggled with.
+To hell, allegiance! Vows, to the blackest devil!
+Conscience and grace, to the profoundest pit!
+I dare damnation. To this point I stand,
+That both the worlds, I give to negligence,
+Let come what comes; only I’ll be reveng’d
+Most throughly for my father.
+
+KING.
+Who shall stay you?
+
+LAERTES.
+My will, not all the world.
+And for my means, I’ll husband them so well,
+They shall go far with little.
+
+KING.
+Good Laertes,
+If you desire to know the certainty
+Of your dear father’s death, is’t writ in your revenge
+That, sweepstake, you will draw both friend and foe,
+Winner and loser?
+
+LAERTES.
+None but his enemies.
+
+KING.
+Will you know them then?
+
+LAERTES.
+To his good friends thus wide I’ll ope my arms;
+And, like the kind life-rendering pelican,
+Repast them with my blood.
+
+KING.
+Why, now you speak
+Like a good child and a true gentleman.
+That I am guiltless of your father’s death,
+And am most sensibly in grief for it,
+It shall as level to your judgement ’pear
+As day does to your eye.
+
+DANES.
+[_Within._] Let her come in.
+
+LAERTES.
+How now! What noise is that?
+
+Re-enter Ophelia, fantastically dressed with straws and flowers.
+
+O heat, dry up my brains. Tears seven times salt,
+Burn out the sense and virtue of mine eye.
+By heaven, thy madness shall be paid by weight,
+Till our scale turn the beam. O rose of May!
+Dear maid, kind sister, sweet Ophelia!
+O heavens, is’t possible a young maid’s wits
+Should be as mortal as an old man’s life?
+Nature is fine in love, and where ’tis fine,
+It sends some precious instance of itself
+After the thing it loves.
+
+OPHELIA.
+[_Sings._]
+   They bore him barefac’d on the bier,
+   Hey non nonny, nonny, hey nonny
+   And on his grave rain’d many a tear.—
+   Fare you well, my dove!
+
+LAERTES.
+Hadst thou thy wits, and didst persuade revenge,
+It could not move thus.
+
+OPHELIA.
+You must sing ‘Down a-down, and you call him a-down-a.’ O, how the
+wheel becomes it! It is the false steward that stole his master’s
+daughter.
+
+LAERTES.
+This nothing’s more than matter.
+
+OPHELIA.
+There’s rosemary, that’s for remembrance; pray love, remember. And
+there is pansies, that’s for thoughts.
+
+LAERTES.
+A document in madness, thoughts and remembrance fitted.
+
+OPHELIA.
+There’s fennel for you, and columbines. There’s rue for you; and here’s
+some for me. We may call it herb of grace o’ Sundays. O you must wear
+your rue with a difference. There’s a daisy. I would give you some
+violets, but they wither’d all when my father died. They say he made a
+good end.
+[_Sings._]
+   For bonny sweet Robin is all my joy.
+
+LAERTES.
+Thought and affliction, passion, hell itself
+She turns to favour and to prettiness.
+
+OPHELIA.
+[_Sings._]
+   And will he not come again?
+   And will he not come again?
+     No, no, he is dead,
+     Go to thy death-bed,
+   He never will come again.
+
+   His beard was as white as snow,
+   All flaxen was his poll.
+     He is gone, he is gone,
+     And we cast away moan.
+   God ha’ mercy on his soul.
+
+And of all Christian souls, I pray God. God b’ wi’ ye.
+
+[_Exit._]
+
+LAERTES.
+Do you see this, O God?
+
+KING.
+Laertes, I must commune with your grief,
+Or you deny me right. Go but apart,
+Make choice of whom your wisest friends you will,
+And they shall hear and judge ’twixt you and me.
+If by direct or by collateral hand
+They find us touch’d, we will our kingdom give,
+Our crown, our life, and all that we call ours
+To you in satisfaction; but if not,
+Be you content to lend your patience to us,
+And we shall jointly labour with your soul
+To give it due content.
+
+LAERTES.
+Let this be so;
+His means of death, his obscure burial,—
+No trophy, sword, nor hatchment o’er his bones,
+No noble rite, nor formal ostentation,—
+Cry to be heard, as ’twere from heaven to earth,
+That I must call’t in question.
+
+KING.
+So you shall.
+And where th’offence is let the great axe fall.
+I pray you go with me.
+
+[_Exeunt._]
+
+ SCENE VI. Another room in the Castle.
+
+Enter Horatio and a Servant.
+
+HORATIO.
+What are they that would speak with me?
+
+SERVANT.
+Sailors, sir. They say they have letters for you.
+
+HORATIO.
+Let them come in.
+
+[_Exit Servant._]
+
+I do not know from what part of the world
+I should be greeted, if not from Lord Hamlet.
+
+Enter Sailors.
+
+FIRST SAILOR.
+God bless you, sir.
+
+HORATIO.
+Let him bless thee too.
+
+FIRST SAILOR.
+He shall, sir, and’t please him. There’s a letter for you, sir. It
+comes from th’ambassador that was bound for England; if your name be
+Horatio, as I am let to know it is.
+
+HORATIO.
+[_Reads._] ‘Horatio, when thou shalt have overlooked this, give these
+fellows some means to the King. They have letters for him. Ere we were
+two days old at sea, a pirate of very warlike appointment gave us
+chase. Finding ourselves too slow of sail, we put on a compelled
+valour, and in the grapple I boarded them. On the instant they got
+clear of our ship, so I alone became their prisoner. They have dealt
+with me like thieves of mercy. But they knew what they did; I am to do
+a good turn for them. Let the King have the letters I have sent, and
+repair thou to me with as much haste as thou wouldst fly death. I have
+words to speak in thine ear will make thee dumb; yet are they much too
+light for the bore of the matter. These good fellows will bring thee
+where I am. Rosencrantz and Guildenstern hold their course for England:
+of them I have much to tell thee. Farewell.
+     He that thou knowest thine,
+     HAMLET.’
+
+Come, I will give you way for these your letters,
+And do’t the speedier, that you may direct me
+To him from whom you brought them.
+
+[_Exeunt._]
+
+ SCENE VII. Another room in the Castle.
+
+Enter King and Laertes.
+
+KING.
+Now must your conscience my acquittance seal,
+And you must put me in your heart for friend,
+Sith you have heard, and with a knowing ear,
+That he which hath your noble father slain
+Pursu’d my life.
+
+LAERTES.
+It well appears. But tell me
+Why you proceeded not against these feats,
+So crimeful and so capital in nature,
+As by your safety, wisdom, all things else,
+You mainly were stirr’d up.
+
+KING.
+O, for two special reasons,
+Which may to you, perhaps, seem much unsinew’d,
+But yet to me they are strong. The Queen his mother
+Lives almost by his looks; and for myself,—
+My virtue or my plague, be it either which,—
+She’s so conjunctive to my life and soul,
+That, as the star moves not but in his sphere,
+I could not but by her. The other motive,
+Why to a public count I might not go,
+Is the great love the general gender bear him,
+Who, dipping all his faults in their affection,
+Would like the spring that turneth wood to stone,
+Convert his gyves to graces; so that my arrows,
+Too slightly timber’d for so loud a wind,
+Would have reverted to my bow again,
+And not where I had aim’d them.
+
+LAERTES.
+And so have I a noble father lost,
+A sister driven into desperate terms,
+Whose worth, if praises may go back again,
+Stood challenger on mount of all the age
+For her perfections. But my revenge will come.
+
+KING.
+Break not your sleeps for that. You must not think
+That we are made of stuff so flat and dull
+That we can let our beard be shook with danger,
+And think it pastime. You shortly shall hear more.
+I lov’d your father, and we love ourself,
+And that, I hope, will teach you to imagine—
+
+Enter a Messenger.
+
+How now? What news?
+
+MESSENGER.
+Letters, my lord, from Hamlet.
+This to your Majesty; this to the Queen.
+
+KING.
+From Hamlet! Who brought them?
+
+MESSENGER.
+Sailors, my lord, they say; I saw them not.
+They were given me by Claudio. He receiv’d them
+Of him that brought them.
+
+KING.
+Laertes, you shall hear them.
+Leave us.
+
+[_Exit Messenger._]
+
+[_Reads._] ‘High and mighty, you shall know I am set naked on your
+kingdom. Tomorrow shall I beg leave to see your kingly eyes. When I
+shall, first asking your pardon thereunto, recount the occasions of my
+sudden and more strange return.
+     HAMLET.’
+
+What should this mean? Are all the rest come back?
+Or is it some abuse, and no such thing?
+
+LAERTES.
+Know you the hand?
+
+KING.
+’Tis Hamlet’s character. ‘Naked!’
+And in a postscript here he says ‘alone.’
+Can you advise me?
+
+LAERTES.
+I am lost in it, my lord. But let him come,
+It warms the very sickness in my heart
+That I shall live and tell him to his teeth,
+‘Thus diest thou.’
+
+KING.
+If it be so, Laertes,—
+As how should it be so? How otherwise?—
+Will you be rul’d by me?
+
+LAERTES.
+Ay, my lord;
+So you will not o’errule me to a peace.
+
+KING.
+To thine own peace. If he be now return’d,
+As checking at his voyage, and that he means
+No more to undertake it, I will work him
+To an exploit, now ripe in my device,
+Under the which he shall not choose but fall;
+And for his death no wind shall breathe,
+But even his mother shall uncharge the practice
+And call it accident.
+
+LAERTES.
+My lord, I will be rul’d;
+The rather if you could devise it so
+That I might be the organ.
+
+KING.
+It falls right.
+You have been talk’d of since your travel much,
+And that in Hamlet’s hearing, for a quality
+Wherein they say you shine. Your sum of parts
+Did not together pluck such envy from him
+As did that one, and that, in my regard,
+Of the unworthiest siege.
+
+LAERTES.
+What part is that, my lord?
+
+KING.
+A very riband in the cap of youth,
+Yet needful too, for youth no less becomes
+The light and careless livery that it wears
+Than settled age his sables and his weeds,
+Importing health and graveness. Two months since
+Here was a gentleman of Normandy,—
+I’ve seen myself, and serv’d against, the French,
+And they can well on horseback, but this gallant
+Had witchcraft in’t. He grew unto his seat,
+And to such wondrous doing brought his horse,
+As had he been incorps’d and demi-natur’d
+With the brave beast. So far he topp’d my thought
+That I in forgery of shapes and tricks,
+Come short of what he did.
+
+LAERTES.
+A Norman was’t?
+
+KING.
+A Norman.
+
+LAERTES.
+Upon my life, Lamord.
+
+KING.
+The very same.
+
+LAERTES.
+I know him well. He is the brooch indeed
+And gem of all the nation.
+
+KING.
+He made confession of you,
+And gave you such a masterly report
+For art and exercise in your defence,
+And for your rapier most especially,
+That he cried out ’twould be a sight indeed
+If one could match you. The scrimers of their nation
+He swore had neither motion, guard, nor eye,
+If you oppos’d them. Sir, this report of his
+Did Hamlet so envenom with his envy
+That he could nothing do but wish and beg
+Your sudden coming o’er to play with him.
+Now, out of this,—
+
+LAERTES.
+What out of this, my lord?
+
+KING.
+Laertes, was your father dear to you?
+Or are you like the painting of a sorrow,
+A face without a heart?
+
+LAERTES.
+Why ask you this?
+
+KING.
+Not that I think you did not love your father,
+But that I know love is begun by time,
+And that I see, in passages of proof,
+Time qualifies the spark and fire of it.
+There lives within the very flame of love
+A kind of wick or snuff that will abate it;
+And nothing is at a like goodness still,
+For goodness, growing to a pleurisy,
+Dies in his own too much. That we would do,
+We should do when we would; for this ‘would’ changes,
+And hath abatements and delays as many
+As there are tongues, are hands, are accidents;
+And then this ‘should’ is like a spendthrift sigh
+That hurts by easing. But to the quick o’ th’ulcer:
+Hamlet comes back: what would you undertake
+To show yourself your father’s son in deed,
+More than in words?
+
+LAERTES.
+To cut his throat i’ th’ church.
+
+KING.
+No place, indeed, should murder sanctuarize;
+Revenge should have no bounds. But good Laertes,
+Will you do this, keep close within your chamber.
+Hamlet return’d shall know you are come home:
+We’ll put on those shall praise your excellence,
+And set a double varnish on the fame
+The Frenchman gave you, bring you in fine together
+And wager on your heads. He, being remiss,
+Most generous, and free from all contriving,
+Will not peruse the foils; so that with ease,
+Or with a little shuffling, you may choose
+A sword unbated, and in a pass of practice,
+Requite him for your father.
+
+LAERTES.
+I will do’t.
+And for that purpose I’ll anoint my sword.
+I bought an unction of a mountebank
+So mortal that, but dip a knife in it,
+Where it draws blood no cataplasm so rare,
+Collected from all simples that have virtue
+Under the moon, can save the thing from death
+This is but scratch’d withal. I’ll touch my point
+With this contagion, that if I gall him slightly,
+It may be death.
+
+KING.
+Let’s further think of this,
+Weigh what convenience both of time and means
+May fit us to our shape. If this should fail,
+And that our drift look through our bad performance.
+’Twere better not assay’d. Therefore this project
+Should have a back or second, that might hold
+If this did blast in proof. Soft, let me see.
+We’ll make a solemn wager on your cunnings,—
+I ha’t! When in your motion you are hot and dry,
+As make your bouts more violent to that end,
+And that he calls for drink, I’ll have prepar’d him
+A chalice for the nonce; whereon but sipping,
+If he by chance escape your venom’d stuck,
+Our purpose may hold there.
+
+Enter Queen.
+
+How now, sweet Queen?
+
+QUEEN.
+One woe doth tread upon another’s heel,
+So fast they follow. Your sister’s drown’d, Laertes.
+
+LAERTES.
+Drown’d! O, where?
+
+QUEEN.
+There is a willow grows aslant a brook,
+That shows his hoary leaves in the glassy stream.
+There with fantastic garlands did she make
+Of crow-flowers, nettles, daisies, and long purples,
+That liberal shepherds give a grosser name,
+But our cold maids do dead men’s fingers call them.
+There on the pendant boughs her coronet weeds
+Clamb’ring to hang, an envious sliver broke,
+When down her weedy trophies and herself
+Fell in the weeping brook. Her clothes spread wide,
+And mermaid-like, awhile they bore her up,
+Which time she chaunted snatches of old tunes,
+As one incapable of her own distress,
+Or like a creature native and indued
+Unto that element. But long it could not be
+Till that her garments, heavy with their drink,
+Pull’d the poor wretch from her melodious lay
+To muddy death.
+
+LAERTES.
+Alas, then she is drown’d?
+
+QUEEN.
+Drown’d, drown’d.
+
+LAERTES.
+Too much of water hast thou, poor Ophelia,
+And therefore I forbid my tears. But yet
+It is our trick; nature her custom holds,
+Let shame say what it will. When these are gone,
+The woman will be out. Adieu, my lord,
+I have a speech of fire, that fain would blaze,
+But that this folly douts it.
+
+[_Exit._]
+
+KING.
+Let’s follow, Gertrude;
+How much I had to do to calm his rage!
+Now fear I this will give it start again;
+Therefore let’s follow.
+
+[_Exeunt._]
+
+
+
+
+ACT V
+
+SCENE I. A churchyard.
+
+
+Enter two Clowns with spades, &c.
+
+FIRST CLOWN.
+Is she to be buried in Christian burial, when she wilfully seeks her
+own salvation?
+
+SECOND CLOWN.
+I tell thee she is, and therefore make her grave straight. The crowner
+hath sat on her, and finds it Christian burial.
+
+FIRST CLOWN.
+How can that be, unless she drowned herself in her own defence?
+
+SECOND CLOWN.
+Why, ’tis found so.
+
+FIRST CLOWN.
+It must be _se offendendo_, it cannot be else. For here lies the point:
+if I drown myself wittingly, it argues an act: and an act hath three
+branches. It is to act, to do, and to perform: argal, she drowned
+herself wittingly.
+
+SECOND CLOWN.
+Nay, but hear you, goodman delver,—
+
+FIRST CLOWN.
+Give me leave. Here lies the water; good. Here stands the man; good. If
+the man go to this water and drown himself, it is, will he nill he, he
+goes,—mark you that. But if the water come to him and drown him, he
+drowns not himself. Argal, he that is not guilty of his own death
+shortens not his own life.
+
+SECOND CLOWN.
+But is this law?
+
+FIRST CLOWN.
+Ay, marry, is’t, crowner’s quest law.
+
+SECOND CLOWN.
+Will you ha’ the truth on’t? If this had not been a gentlewoman, she
+should have been buried out o’ Christian burial.
+
+FIRST CLOWN.
+Why, there thou say’st. And the more pity that great folk should have
+countenance in this world to drown or hang themselves more than their
+even Christian. Come, my spade. There is no ancient gentlemen but
+gardeners, ditchers, and grave-makers: they hold up Adam’s profession.
+
+SECOND CLOWN.
+Was he a gentleman?
+
+FIRST CLOWN.
+He was the first that ever bore arms.
+
+SECOND CLOWN.
+Why, he had none.
+
+FIRST CLOWN.
+What, art a heathen? How dost thou understand the Scripture? The
+Scripture says Adam digg’d. Could he dig without arms? I’ll put another
+question to thee. If thou answerest me not to the purpose, confess
+thyself—
+
+SECOND CLOWN.
+Go to.
+
+FIRST CLOWN.
+What is he that builds stronger than either the mason, the shipwright,
+or the carpenter?
+
+SECOND CLOWN.
+The gallows-maker; for that frame outlives a thousand tenants.
+
+FIRST CLOWN.
+I like thy wit well in good faith, the gallows does well. But how does
+it well? It does well to those that do ill. Now, thou dost ill to say
+the gallows is built stronger than the church; argal, the gallows may
+do well to thee. To’t again, come.
+
+SECOND CLOWN.
+Who builds stronger than a mason, a shipwright, or a carpenter?
+
+FIRST CLOWN.
+Ay, tell me that, and unyoke.
+
+SECOND CLOWN.
+Marry, now I can tell.
+
+FIRST CLOWN.
+To’t.
+
+SECOND CLOWN.
+Mass, I cannot tell.
+
+Enter Hamlet and Horatio, at a distance.
+
+FIRST CLOWN.
+Cudgel thy brains no more about it, for your dull ass will not mend his
+pace with beating; and when you are asked this question next, say ‘a
+grave-maker’. The houses he makes last till doomsday. Go, get thee to
+Yaughan; fetch me a stoup of liquor.
+
+[_Exit Second Clown._]
+
+[_Digs and sings._]
+
+   In youth when I did love, did love,
+     Methought it was very sweet;
+   To contract, O, the time for, a, my behove,
+     O methought there was nothing meet.
+
+HAMLET.
+Has this fellow no feeling of his business, that he sings at
+grave-making?
+
+HORATIO.
+Custom hath made it in him a property of easiness.
+
+HAMLET.
+’Tis e’en so; the hand of little employment hath the daintier sense.
+
+FIRST CLOWN.
+[_Sings._]
+   But age with his stealing steps
+     Hath claw’d me in his clutch,
+   And hath shipp’d me into the land,
+     As if I had never been such.
+
+[_Throws up a skull._]
+
+HAMLET.
+That skull had a tongue in it, and could sing once. How the knave jowls
+it to th’ ground, as if ’twere Cain’s jawbone, that did the first
+murder! This might be the pate of a politician which this ass now
+o’er-offices, one that would circumvent God, might it not?
+
+HORATIO.
+It might, my lord.
+
+HAMLET.
+Or of a courtier, which could say ‘Good morrow, sweet lord! How dost
+thou, good lord?’ This might be my lord such-a-one, that praised my
+lord such-a-one’s horse when he meant to beg it, might it not?
+
+HORATIO.
+Ay, my lord.
+
+HAMLET.
+Why, e’en so: and now my Lady Worm’s; chapless, and knocked about the
+mazard with a sexton’s spade. Here’s fine revolution, an we had the
+trick to see’t. Did these bones cost no more the breeding but to play
+at loggets with ’em? Mine ache to think on’t.
+
+FIRST CLOWN.
+[_Sings._]
+   A pickaxe and a spade, a spade,
+     For and a shrouding-sheet;
+   O, a pit of clay for to be made
+     For such a guest is meet.
+
+[_Throws up another skull._]
+
+HAMLET.
+There’s another. Why may not that be the skull of a lawyer? Where be
+his quiddits now, his quillets, his cases, his tenures, and his tricks?
+Why does he suffer this rude knave now to knock him about the sconce
+with a dirty shovel, and will not tell him of his action of battery?
+Hum. This fellow might be in’s time a great buyer of land, with his
+statutes, his recognizances, his fines, his double vouchers, his
+recoveries. Is this the fine of his fines, and the recovery of his
+recoveries, to have his fine pate full of fine dirt? Will his vouchers
+vouch him no more of his purchases, and double ones too, than the
+length and breadth of a pair of indentures? The very conveyances of his
+lands will scarcely lie in this box; and must the inheritor himself
+have no more, ha?
+
+HORATIO.
+Not a jot more, my lord.
+
+HAMLET.
+Is not parchment made of sheep-skins?
+
+HORATIO.
+Ay, my lord, and of calf-skins too.
+
+HAMLET.
+They are sheep and calves which seek out assurance in that. I will
+speak to this fellow.—Whose grave’s this, sir?
+
+FIRST CLOWN.
+Mine, sir.
+[_Sings._]
+   O, a pit of clay for to be made
+     For such a guest is meet.
+
+HAMLET.
+I think it be thine indeed, for thou liest in’t.
+
+FIRST CLOWN.
+You lie out on’t, sir, and therefore ’tis not yours.
+For my part, I do not lie in’t, yet it is mine.
+
+HAMLET.
+Thou dost lie in’t, to be in’t and say it is thine. ’Tis for the dead,
+not for the quick; therefore thou liest.
+
+FIRST CLOWN.
+’Tis a quick lie, sir; ’t will away again from me to you.
+
+HAMLET.
+What man dost thou dig it for?
+
+FIRST CLOWN.
+For no man, sir.
+
+HAMLET.
+What woman then?
+
+FIRST CLOWN.
+For none neither.
+
+HAMLET.
+Who is to be buried in’t?
+
+FIRST CLOWN.
+One that was a woman, sir; but, rest her soul, she’s dead.
+
+HAMLET.
+How absolute the knave is! We must speak by the card, or equivocation
+will undo us. By the Lord, Horatio, these three years I have taken note
+of it, the age is grown so picked that the toe of the peasant comes so
+near the heel of the courtier he galls his kibe.—How long hast thou
+been a grave-maker?
+
+FIRST CLOWN.
+Of all the days i’ th’ year, I came to’t that day that our last King
+Hamlet o’ercame Fortinbras.
+
+HAMLET.
+How long is that since?
+
+FIRST CLOWN.
+Cannot you tell that? Every fool can tell that. It was the very day
+that young Hamlet was born,—he that is mad, and sent into England.
+
+HAMLET.
+Ay, marry, why was he sent into England?
+
+FIRST CLOWN.
+Why, because he was mad; he shall recover his wits there; or if he do
+not, it’s no great matter there.
+
+HAMLET.
+Why?
+
+FIRST CLOWN.
+’Twill not be seen in him there; there the men are as mad as he.
+
+HAMLET.
+How came he mad?
+
+FIRST CLOWN.
+Very strangely, they say.
+
+HAMLET.
+How strangely?
+
+FIRST CLOWN.
+Faith, e’en with losing his wits.
+
+HAMLET.
+Upon what ground?
+
+FIRST CLOWN.
+Why, here in Denmark. I have been sexton here, man and boy, thirty
+years.
+
+HAMLET.
+How long will a man lie i’ th’earth ere he rot?
+
+FIRST CLOWN.
+Faith, if he be not rotten before he die,—as we have many pocky corses
+nowadays that will scarce hold the laying in,—he will last you some
+eight year or nine year. A tanner will last you nine year.
+
+HAMLET.
+Why he more than another?
+
+FIRST CLOWN.
+Why, sir, his hide is so tann’d with his trade that he will keep out
+water a great while. And your water is a sore decayer of your whoreson
+dead body. Here’s a skull now; this skull hath lain in the earth
+three-and-twenty years.
+
+HAMLET.
+Whose was it?
+
+FIRST CLOWN.
+A whoreson, mad fellow’s it was. Whose do you think it was?
+
+HAMLET.
+Nay, I know not.
+
+FIRST CLOWN.
+A pestilence on him for a mad rogue! A pour’d a flagon of Rhenish on my
+head once. This same skull, sir, was Yorick’s skull, the King’s jester.
+
+HAMLET.
+This?
+
+FIRST CLOWN.
+E’en that.
+
+HAMLET.
+Let me see. [_Takes the skull._] Alas, poor Yorick. I knew him,
+Horatio, a fellow of infinite jest, of most excellent fancy. He hath
+borne me on his back a thousand times; and now, how abhorred in my
+imagination it is! My gorge rises at it. Here hung those lips that I
+have kiss’d I know not how oft. Where be your gibes now? your gambols?
+your songs? your flashes of merriment, that were wont to set the table
+on a roar? Not one now, to mock your own grinning? Quite chop-fallen?
+Now get you to my lady’s chamber, and tell her, let her paint an inch
+thick, to this favour she must come. Make her laugh at that.—Prithee,
+Horatio, tell me one thing.
+
+HORATIO.
+What’s that, my lord?
+
+HAMLET.
+Dost thou think Alexander looked o’ this fashion i’ th’earth?
+
+HORATIO.
+E’en so.
+
+HAMLET.
+And smelt so? Pah!
+
+[_Throws down the skull._]
+
+HORATIO.
+E’en so, my lord.
+
+HAMLET.
+To what base uses we may return, Horatio! Why may not imagination trace
+the noble dust of Alexander till he find it stopping a bung-hole?
+
+HORATIO.
+’Twere to consider too curiously to consider so.
+
+HAMLET.
+No, faith, not a jot. But to follow him thither with modesty enough,
+and likelihood to lead it; as thus. Alexander died, Alexander was
+buried, Alexander returneth into dust; the dust is earth; of earth we
+make loam; and why of that loam whereto he was converted might they not
+stop a beer-barrel?
+Imperious Caesar, dead and turn’d to clay,
+Might stop a hole to keep the wind away.
+O, that that earth which kept the world in awe
+Should patch a wall t’expel the winter’s flaw.
+But soft! but soft! aside! Here comes the King.
+
+Enter priests, &c, in procession; the corpse of Ophelia, Laertes and
+Mourners following; King, Queen, their Trains, &c.
+
+The Queen, the courtiers. Who is that they follow?
+And with such maimed rites? This doth betoken
+The corse they follow did with desperate hand
+Fordo it own life. ’Twas of some estate.
+Couch we awhile and mark.
+
+[_Retiring with Horatio._]
+
+LAERTES.
+What ceremony else?
+
+HAMLET.
+That is Laertes, a very noble youth. Mark.
+
+LAERTES.
+What ceremony else?
+
+PRIEST.
+Her obsequies have been as far enlarg’d
+As we have warranties. Her death was doubtful;
+And but that great command o’ersways the order,
+She should in ground unsanctified have lodg’d
+Till the last trumpet. For charitable prayers,
+Shards, flints, and pebbles should be thrown on her.
+Yet here she is allowed her virgin rites,
+Her maiden strewments, and the bringing home
+Of bell and burial.
+
+LAERTES.
+Must there no more be done?
+
+PRIEST.
+No more be done.
+We should profane the service of the dead
+To sing sage requiem and such rest to her
+As to peace-parted souls.
+
+LAERTES.
+Lay her i’ th’earth,
+And from her fair and unpolluted flesh
+May violets spring. I tell thee, churlish priest,
+A minist’ring angel shall my sister be
+When thou liest howling.
+
+HAMLET.
+What, the fair Ophelia?
+
+QUEEN.
+[_Scattering flowers._] Sweets to the sweet. Farewell.
+I hop’d thou shouldst have been my Hamlet’s wife;
+I thought thy bride-bed to have deck’d, sweet maid,
+And not have strew’d thy grave.
+
+LAERTES.
+O, treble woe
+Fall ten times treble on that cursed head
+Whose wicked deed thy most ingenious sense
+Depriv’d thee of. Hold off the earth a while,
+Till I have caught her once more in mine arms.
+[_Leaps into the grave._]
+Now pile your dust upon the quick and dead,
+Till of this flat a mountain you have made,
+To o’ertop old Pelion or the skyish head
+Of blue Olympus.
+
+HAMLET.
+[_Advancing._]
+What is he whose grief
+Bears such an emphasis? whose phrase of sorrow
+Conjures the wand’ring stars, and makes them stand
+Like wonder-wounded hearers? This is I,
+Hamlet the Dane.
+[_Leaps into the grave._]
+
+LAERTES.
+[_Grappling with him._] The devil take thy soul!
+
+HAMLET.
+Thou pray’st not well.
+I prithee take thy fingers from my throat;
+For though I am not splenative and rash,
+Yet have I in me something dangerous,
+Which let thy wiseness fear. Away thy hand!
+
+KING.
+Pluck them asunder.
+
+QUEEN.
+Hamlet! Hamlet!
+
+All.
+Gentlemen!
+
+HORATIO.
+Good my lord, be quiet.
+
+[_The Attendants part them, and they come out of the grave._]
+
+HAMLET.
+Why, I will fight with him upon this theme
+Until my eyelids will no longer wag.
+
+QUEEN.
+O my son, what theme?
+
+HAMLET.
+I lov’d Ophelia; forty thousand brothers
+Could not, with all their quantity of love,
+Make up my sum. What wilt thou do for her?
+
+KING.
+O, he is mad, Laertes.
+
+QUEEN.
+For love of God forbear him!
+
+HAMLET.
+’Swounds, show me what thou’lt do:
+Woul’t weep? woul’t fight? woul’t fast? woul’t tear thyself?
+Woul’t drink up eisel? eat a crocodile?
+I’ll do’t. Dost thou come here to whine?
+To outface me with leaping in her grave?
+Be buried quick with her, and so will I.
+And if thou prate of mountains, let them throw
+Millions of acres on us, till our ground,
+Singeing his pate against the burning zone,
+Make Ossa like a wart. Nay, an thou’lt mouth,
+I’ll rant as well as thou.
+
+QUEEN.
+This is mere madness:
+And thus awhile the fit will work on him;
+Anon, as patient as the female dove,
+When that her golden couplets are disclos’d,
+His silence will sit drooping.
+
+HAMLET.
+Hear you, sir;
+What is the reason that you use me thus?
+I lov’d you ever. But it is no matter.
+Let Hercules himself do what he may,
+The cat will mew, and dog will have his day.
+
+[_Exit._]
+
+KING.
+I pray thee, good Horatio, wait upon him.
+
+[_Exit Horatio._]
+
+[_To Laertes_]
+Strengthen your patience in our last night’s speech;
+We’ll put the matter to the present push.—
+Good Gertrude, set some watch over your son.
+This grave shall have a living monument.
+An hour of quiet shortly shall we see;
+Till then in patience our proceeding be.
+
+[_Exeunt._]
+
+ SCENE II. A hall in the Castle.
+
+Enter Hamlet and Horatio.
+
+HAMLET.
+So much for this, sir. Now let me see the other;
+You do remember all the circumstance?
+
+HORATIO.
+Remember it, my lord!
+
+HAMLET.
+Sir, in my heart there was a kind of fighting
+That would not let me sleep. Methought I lay
+Worse than the mutinies in the bilboes. Rashly,
+And prais’d be rashness for it,—let us know,
+Our indiscretion sometime serves us well,
+When our deep plots do pall; and that should teach us
+There’s a divinity that shapes our ends,
+Rough-hew them how we will.
+
+HORATIO.
+That is most certain.
+
+HAMLET.
+Up from my cabin,
+My sea-gown scarf’d about me, in the dark
+Grop’d I to find out them; had my desire,
+Finger’d their packet, and in fine, withdrew
+To mine own room again, making so bold,
+My fears forgetting manners, to unseal
+Their grand commission; where I found, Horatio,
+Oh royal knavery! an exact command,
+Larded with many several sorts of reasons,
+Importing Denmark’s health, and England’s too,
+With ho! such bugs and goblins in my life,
+That on the supervise, no leisure bated,
+No, not to stay the grinding of the axe,
+My head should be struck off.
+
+HORATIO.
+Is’t possible?
+
+HAMLET.
+Here’s the commission, read it at more leisure.
+But wilt thou hear me how I did proceed?
+
+HORATIO.
+I beseech you.
+
+HAMLET.
+Being thus benetted round with villanies,—
+Or I could make a prologue to my brains,
+They had begun the play,—I sat me down,
+Devis’d a new commission, wrote it fair:
+I once did hold it, as our statists do,
+A baseness to write fair, and labour’d much
+How to forget that learning; but, sir, now
+It did me yeoman’s service. Wilt thou know
+The effect of what I wrote?
+
+HORATIO.
+Ay, good my lord.
+
+HAMLET.
+An earnest conjuration from the King,
+As England was his faithful tributary,
+As love between them like the palm might flourish,
+As peace should still her wheaten garland wear
+And stand a comma ’tween their amities,
+And many such-like ‘as’es of great charge,
+That on the view and know of these contents,
+Without debatement further, more or less,
+He should the bearers put to sudden death,
+Not shriving-time allow’d.
+
+HORATIO.
+How was this seal’d?
+
+HAMLET.
+Why, even in that was heaven ordinant.
+I had my father’s signet in my purse,
+Which was the model of that Danish seal:
+Folded the writ up in the form of the other,
+Subscrib’d it: gave’t th’impression; plac’d it safely,
+The changeling never known. Now, the next day
+Was our sea-fight, and what to this was sequent
+Thou know’st already.
+
+HORATIO.
+So Guildenstern and Rosencrantz go to’t.
+
+HAMLET.
+Why, man, they did make love to this employment.
+They are not near my conscience; their defeat
+Does by their own insinuation grow.
+’Tis dangerous when the baser nature comes
+Between the pass and fell incensed points
+Of mighty opposites.
+
+HORATIO.
+Why, what a king is this!
+
+HAMLET.
+Does it not, thinks’t thee, stand me now upon,—
+He that hath kill’d my king, and whor’d my mother,
+Popp’d in between th’election and my hopes,
+Thrown out his angle for my proper life,
+And with such cozenage—is’t not perfect conscience
+To quit him with this arm? And is’t not to be damn’d
+To let this canker of our nature come
+In further evil?
+
+HORATIO.
+It must be shortly known to him from England
+What is the issue of the business there.
+
+HAMLET.
+It will be short. The interim is mine;
+And a man’s life’s no more than to say ‘One’.
+But I am very sorry, good Horatio,
+That to Laertes I forgot myself;
+For by the image of my cause I see
+The portraiture of his. I’ll court his favours.
+But sure the bravery of his grief did put me
+Into a tow’ring passion.
+
+HORATIO.
+Peace, who comes here?
+
+Enter Osric.
+
+OSRIC.
+Your lordship is right welcome back to Denmark.
+
+HAMLET.
+I humbly thank you, sir. Dost know this waterfly?
+
+HORATIO.
+No, my good lord.
+
+HAMLET.
+Thy state is the more gracious; for ’tis a vice to know him. He hath
+much land, and fertile; let a beast be lord of beasts, and his crib
+shall stand at the king’s mess; ’tis a chough; but, as I say, spacious
+in the possession of dirt.
+
+OSRIC.
+Sweet lord, if your lordship were at leisure, I should impart a thing
+to you from his Majesty.
+
+HAMLET.
+I will receive it with all diligence of spirit. Put your bonnet to his
+right use; ’tis for the head.
+
+OSRIC.
+I thank your lordship, ’tis very hot.
+
+HAMLET.
+No, believe me, ’tis very cold, the wind is northerly.
+
+OSRIC.
+It is indifferent cold, my lord, indeed.
+
+HAMLET.
+Methinks it is very sultry and hot for my complexion.
+
+OSRIC.
+Exceedingly, my lord; it is very sultry,—as ’twere—I cannot tell how.
+But, my lord, his Majesty bade me signify to you that he has laid a
+great wager on your head. Sir, this is the matter,—
+
+HAMLET.
+I beseech you, remember,—
+
+[_Hamlet moves him to put on his hat._]
+
+OSRIC.
+Nay, in good faith; for mine ease, in good faith. Sir, here is newly
+come to court Laertes; believe me, an absolute gentleman, full of most
+excellent differences, of very soft society and great showing. Indeed,
+to speak feelingly of him, he is the card or calendar of gentry; for
+you shall find in him the continent of what part a gentleman would see.
+
+HAMLET.
+Sir, his definement suffers no perdition in you, though I know, to
+divide him inventorially would dizzy th’arithmetic of memory, and yet
+but yaw neither, in respect of his quick sail. But, in the verity of
+extolment, I take him to be a soul of great article and his infusion of
+such dearth and rareness as, to make true diction of him, his semblable
+is his mirror and who else would trace him his umbrage, nothing more.
+
+OSRIC.
+Your lordship speaks most infallibly of him.
+
+HAMLET.
+The concernancy, sir? Why do we wrap the gentleman in our more rawer
+breath?
+
+OSRIC.
+Sir?
+
+HORATIO.
+Is’t not possible to understand in another tongue? You will do’t, sir,
+really.
+
+HAMLET.
+What imports the nomination of this gentleman?
+
+OSRIC.
+Of Laertes?
+
+HORATIO.
+His purse is empty already, all’s golden words are spent.
+
+HAMLET.
+Of him, sir.
+
+OSRIC.
+I know you are not ignorant,—
+
+HAMLET.
+I would you did, sir; yet in faith if you did, it would not much
+approve me. Well, sir?
+
+OSRIC.
+You are not ignorant of what excellence Laertes is,—
+
+HAMLET.
+I dare not confess that, lest I should compare with him in excellence;
+but to know a man well were to know himself.
+
+OSRIC.
+I mean, sir, for his weapon; but in the imputation laid on him, by them
+in his meed he’s unfellowed.
+
+HAMLET.
+What’s his weapon?
+
+OSRIC.
+Rapier and dagger.
+
+HAMLET.
+That’s two of his weapons. But well.
+
+OSRIC.
+The King, sir, hath wager’d with him six Barbary horses, against the
+which he has imponed, as I take it, six French rapiers and poniards,
+with their assigns, as girdle, hangers, and so. Three of the carriages,
+in faith, are very dear to fancy, very responsive to the hilts, most
+delicate carriages, and of very liberal conceit.
+
+HAMLET.
+What call you the carriages?
+
+HORATIO.
+I knew you must be edified by the margin ere you had done.
+
+OSRIC.
+The carriages, sir, are the hangers.
+
+HAMLET.
+The phrase would be more german to the matter if we could carry cannon
+by our sides. I would it might be hangers till then. But on. Six
+Barbary horses against six French swords, their assigns, and three
+liberal conceited carriages: that’s the French bet against the Danish.
+Why is this all imponed, as you call it?
+
+OSRIC.
+The King, sir, hath laid that in a dozen passes between you and him, he
+shall not exceed you three hits. He hath laid on twelve for nine. And
+it would come to immediate trial if your lordship would vouchsafe the
+answer.
+
+HAMLET.
+How if I answer no?
+
+OSRIC.
+I mean, my lord, the opposition of your person in trial.
+
+HAMLET.
+Sir, I will walk here in the hall. If it please his Majesty, it is the
+breathing time of day with me. Let the foils be brought, the gentleman
+willing, and the King hold his purpose, I will win for him if I can; if
+not, I will gain nothing but my shame and the odd hits.
+
+OSRIC.
+Shall I re-deliver you e’en so?
+
+HAMLET.
+To this effect, sir; after what flourish your nature will.
+
+OSRIC.
+I commend my duty to your lordship.
+
+HAMLET.
+Yours, yours.
+
+[_Exit Osric._]
+
+He does well to commend it himself, there are no tongues else for’s
+turn.
+
+HORATIO.
+This lapwing runs away with the shell on his head.
+
+HAMLET.
+He did comply with his dug before he suck’d it. Thus has he,—and many
+more of the same bevy that I know the drossy age dotes on,— only got
+the tune of the time and outward habit of encounter; a kind of yeasty
+collection, which carries them through and through the most fanned and
+winnowed opinions; and do but blow them to their trial, the bubbles are
+out.
+
+Enter a Lord.
+
+LORD.
+My lord, his Majesty commended him to you by young Osric, who brings
+back to him that you attend him in the hall. He sends to know if your
+pleasure hold to play with Laertes or that you will take longer time.
+
+HAMLET.
+I am constant to my purposes, they follow the King’s pleasure. If his
+fitness speaks, mine is ready. Now or whensoever, provided I be so able
+as now.
+
+LORD.
+The King and Queen and all are coming down.
+
+HAMLET.
+In happy time.
+
+LORD.
+The Queen desires you to use some gentle entertainment to Laertes
+before you fall to play.
+
+HAMLET.
+She well instructs me.
+
+[_Exit Lord._]
+
+HORATIO.
+You will lose this wager, my lord.
+
+HAMLET.
+I do not think so. Since he went into France, I have been in continual
+practice. I shall win at the odds. But thou wouldst not think how ill
+all’s here about my heart: but it is no matter.
+
+HORATIO.
+Nay, good my lord.
+
+HAMLET.
+It is but foolery; but it is such a kind of gain-giving as would
+perhaps trouble a woman.
+
+HORATIO.
+If your mind dislike anything, obey it. I will forestall their repair
+hither, and say you are not fit.
+
+HAMLET.
+Not a whit, we defy augury. There’s a special providence in the fall of
+a sparrow. If it be now, ’tis not to come; if it be not to come, it
+will be now; if it be not now, yet it will come. The readiness is all.
+Since no man has aught of what he leaves, what is’t to leave betimes?
+
+Enter King, Queen, Laertes, Lords, Osric and Attendants with foils &c.
+
+KING.
+Come, Hamlet, come, and take this hand from me.
+
+[_The King puts Laertes’s hand into Hamlet’s._]
+
+HAMLET.
+Give me your pardon, sir. I have done you wrong;
+But pardon’t as you are a gentleman.
+This presence knows, and you must needs have heard,
+How I am punish’d with sore distraction.
+What I have done
+That might your nature, honour, and exception
+Roughly awake, I here proclaim was madness.
+Was’t Hamlet wrong’d Laertes? Never Hamlet.
+If Hamlet from himself be ta’en away,
+And when he’s not himself does wrong Laertes,
+Then Hamlet does it not, Hamlet denies it.
+Who does it, then? His madness. If’t be so,
+Hamlet is of the faction that is wrong’d;
+His madness is poor Hamlet’s enemy.
+Sir, in this audience,
+Let my disclaiming from a purpos’d evil
+Free me so far in your most generous thoughts
+That I have shot my arrow o’er the house
+And hurt my brother.
+
+LAERTES.
+I am satisfied in nature,
+Whose motive in this case should stir me most
+To my revenge. But in my terms of honour
+I stand aloof, and will no reconcilement
+Till by some elder masters of known honour
+I have a voice and precedent of peace
+To keep my name ungor’d. But till that time
+I do receive your offer’d love like love,
+And will not wrong it.
+
+HAMLET.
+I embrace it freely,
+And will this brother’s wager frankly play.—
+Give us the foils; come on.
+
+LAERTES.
+Come, one for me.
+
+HAMLET.
+I’ll be your foil, Laertes; in mine ignorance
+Your skill shall like a star i’ th’ darkest night,
+Stick fiery off indeed.
+
+LAERTES.
+You mock me, sir.
+
+HAMLET.
+No, by this hand.
+
+KING.
+Give them the foils, young Osric. Cousin Hamlet,
+You know the wager?
+
+HAMLET.
+Very well, my lord.
+Your Grace has laid the odds o’ the weaker side.
+
+KING.
+I do not fear it. I have seen you both;
+But since he is better’d, we have therefore odds.
+
+LAERTES.
+This is too heavy. Let me see another.
+
+HAMLET.
+This likes me well. These foils have all a length?
+
+[_They prepare to play._]
+
+OSRIC.
+Ay, my good lord.
+
+KING.
+Set me the stoups of wine upon that table.
+If Hamlet give the first or second hit,
+Or quit in answer of the third exchange,
+Let all the battlements their ordnance fire;
+The King shall drink to Hamlet’s better breath,
+And in the cup an union shall he throw
+Richer than that which four successive kings
+In Denmark’s crown have worn. Give me the cups;
+And let the kettle to the trumpet speak,
+The trumpet to the cannoneer without,
+The cannons to the heavens, the heavens to earth,
+‘Now the King drinks to Hamlet.’ Come, begin.
+And you, the judges, bear a wary eye.
+
+HAMLET.
+Come on, sir.
+
+LAERTES.
+Come, my lord.
+
+[_They play._]
+
+HAMLET.
+One.
+
+LAERTES.
+No.
+
+HAMLET.
+Judgement.
+
+OSRIC.
+A hit, a very palpable hit.
+
+LAERTES.
+Well; again.
+
+KING.
+Stay, give me drink. Hamlet, this pearl is thine;
+Here’s to thy health.
+
+[_Trumpets sound, and cannon shot off within._]
+
+Give him the cup.
+
+HAMLET.
+I’ll play this bout first; set it by awhile.
+
+[_They play._]
+
+Come. Another hit; what say you?
+
+LAERTES.
+A touch, a touch, I do confess.
+
+KING.
+Our son shall win.
+
+QUEEN.
+He’s fat, and scant of breath.
+Here, Hamlet, take my napkin, rub thy brows.
+The Queen carouses to thy fortune, Hamlet.
+
+HAMLET.
+Good madam.
+
+KING.
+Gertrude, do not drink.
+
+QUEEN.
+I will, my lord; I pray you pardon me.
+
+KING.
+[_Aside._] It is the poison’d cup; it is too late.
+
+HAMLET.
+I dare not drink yet, madam. By and by.
+
+QUEEN.
+Come, let me wipe thy face.
+
+LAERTES.
+My lord, I’ll hit him now.
+
+KING.
+I do not think’t.
+
+LAERTES.
+[_Aside._] And yet ’tis almost ’gainst my conscience.
+
+HAMLET.
+Come for the third, Laertes. You do but dally.
+I pray you pass with your best violence.
+I am afeard you make a wanton of me.
+
+LAERTES.
+Say you so? Come on.
+
+[_They play._]
+
+OSRIC.
+Nothing neither way.
+
+LAERTES.
+Have at you now.
+
+[_Laertes wounds Hamlet; then, in scuffling, they change rapiers, and
+Hamlet wounds Laertes._]
+
+KING.
+Part them; they are incens’d.
+
+HAMLET.
+Nay, come again!
+
+[_The Queen falls._]
+
+OSRIC.
+Look to the Queen there, ho!
+
+HORATIO.
+They bleed on both sides. How is it, my lord?
+
+OSRIC.
+How is’t, Laertes?
+
+LAERTES.
+Why, as a woodcock to my own springe, Osric.
+I am justly kill’d with mine own treachery.
+
+HAMLET.
+How does the Queen?
+
+KING.
+She swoons to see them bleed.
+
+QUEEN.
+No, no, the drink, the drink! O my dear Hamlet!
+The drink, the drink! I am poison’d.
+
+[_Dies._]
+
+HAMLET.
+O villany! Ho! Let the door be lock’d:
+Treachery! Seek it out.
+
+[_Laertes falls._]
+
+LAERTES.
+It is here, Hamlet. Hamlet, thou art slain.
+No medicine in the world can do thee good.
+In thee there is not half an hour of life;
+The treacherous instrument is in thy hand,
+Unbated and envenom’d. The foul practice
+Hath turn’d itself on me. Lo, here I lie,
+Never to rise again. Thy mother’s poison’d.
+I can no more. The King, the King’s to blame.
+
+HAMLET.
+The point envenom’d too!
+Then, venom, to thy work.
+
+[_Stabs the King._]
+
+OSRIC and LORDS.
+Treason! treason!
+
+KING.
+O yet defend me, friends. I am but hurt.
+
+HAMLET.
+Here, thou incestuous, murderous, damned Dane,
+Drink off this potion. Is thy union here?
+Follow my mother.
+
+[_King dies._]
+
+LAERTES.
+He is justly serv’d.
+It is a poison temper’d by himself.
+Exchange forgiveness with me, noble Hamlet.
+Mine and my father’s death come not upon thee,
+Nor thine on me.
+
+[_Dies._]
+
+HAMLET.
+Heaven make thee free of it! I follow thee.
+I am dead, Horatio. Wretched Queen, adieu.
+You that look pale and tremble at this chance,
+That are but mutes or audience to this act,
+Had I but time,—as this fell sergeant, death,
+Is strict in his arrest,—O, I could tell you,—
+But let it be. Horatio, I am dead,
+Thou liv’st; report me and my cause aright
+To the unsatisfied.
+
+HORATIO.
+Never believe it.
+I am more an antique Roman than a Dane.
+Here’s yet some liquor left.
+
+HAMLET.
+As th’art a man,
+Give me the cup. Let go; by Heaven, I’ll have’t.
+O good Horatio, what a wounded name,
+Things standing thus unknown, shall live behind me.
+If thou didst ever hold me in thy heart,
+Absent thee from felicity awhile,
+And in this harsh world draw thy breath in pain,
+To tell my story.
+
+[_March afar off, and shot within._]
+
+What warlike noise is this?
+
+OSRIC.
+Young Fortinbras, with conquest come from Poland,
+To the ambassadors of England gives
+This warlike volley.
+
+HAMLET.
+O, I die, Horatio.
+The potent poison quite o’er-crows my spirit:
+I cannot live to hear the news from England,
+But I do prophesy th’election lights
+On Fortinbras. He has my dying voice.
+So tell him, with the occurrents more and less,
+Which have solicited. The rest is silence.
+
+[_Dies._]
+
+HORATIO.
+Now cracks a noble heart. Good night, sweet prince,
+And flights of angels sing thee to thy rest.
+Why does the drum come hither?
+
+[_March within._]
+
+Enter Fortinbras, the English Ambassadors and others.
+
+FORTINBRAS.
+Where is this sight?
+
+HORATIO.
+What is it you would see?
+If aught of woe or wonder, cease your search.
+
+FORTINBRAS.
+This quarry cries on havoc. O proud death,
+What feast is toward in thine eternal cell,
+That thou so many princes at a shot
+So bloodily hast struck?
+
+FIRST AMBASSADOR.
+The sight is dismal;
+And our affairs from England come too late.
+The ears are senseless that should give us hearing,
+To tell him his commandment is fulfill’d,
+That Rosencrantz and Guildenstern are dead.
+Where should we have our thanks?
+
+HORATIO.
+Not from his mouth,
+Had it th’ability of life to thank you.
+He never gave commandment for their death.
+But since, so jump upon this bloody question,
+You from the Polack wars, and you from England
+Are here arriv’d, give order that these bodies
+High on a stage be placed to the view,
+And let me speak to th’ yet unknowing world
+How these things came about. So shall you hear
+Of carnal, bloody and unnatural acts,
+Of accidental judgements, casual slaughters,
+Of deaths put on by cunning and forc’d cause,
+And, in this upshot, purposes mistook
+Fall’n on the inventors’ heads. All this can I
+Truly deliver.
+
+FORTINBRAS.
+Let us haste to hear it,
+And call the noblest to the audience.
+For me, with sorrow I embrace my fortune.
+I have some rights of memory in this kingdom,
+Which now to claim my vantage doth invite me.
+
+HORATIO.
+Of that I shall have also cause to speak,
+And from his mouth whose voice will draw on more.
+But let this same be presently perform’d,
+Even while men’s minds are wild, lest more mischance
+On plots and errors happen.
+
+FORTINBRAS.
+Let four captains
+Bear Hamlet like a soldier to the stage,
+For he was likely, had he been put on,
+To have prov’d most royally; and for his passage,
+The soldiers’ music and the rites of war
+Speak loudly for him.
+Take up the bodies. Such a sight as this
+Becomes the field, but here shows much amiss.
+Go, bid the soldiers shoot.
+
+[_A dead march._]
+
+[_Exeunt, bearing off the bodies, after which a peal of ordnance is
+shot off._]
+
+
+
+
+
+        
+            *** END OF THE PROJECT GUTENBERG EBOOK HAMLET, PRINCE OF DENMARK ***
+        
+
+    
+
+Updated editions will replace the previous one—the old editions will
+be renamed.
+
+Creating the works from print editions not protected by U.S. copyright
+law means that no one owns a United States copyright in these works,
+so the Foundation (and you!) can copy and distribute it in the United
+States without permission and without paying copyright
+royalties. Special rules, set forth in the General Terms of Use part
+of this license, apply to copying and distributing Project
+Gutenberg™ electronic works to protect the PROJECT GUTENBERG™
+concept and trademark. Project Gutenberg is a registered trademark,
+and may not be used if you charge for an eBook, except by following
+the terms of the trademark license, including paying royalties for use
+of the Project Gutenberg trademark. If you do not charge anything for
+copies of this eBook, complying with the trademark license is very
+easy. You may use this eBook for nearly any purpose such as creation
+of derivative works, reports, performances and research. Project
+Gutenberg eBooks may be modified and printed and given away—you may
+do practically ANYTHING in the United States with eBooks not protected
+by U.S. copyright law. Redistribution is subject to the trademark
+license, especially commercial redistribution.
+
+
+START: FULL LICENSE
+
+THE FULL PROJECT GUTENBERG LICENSE
+
+PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK
+
+To protect the Project Gutenberg™ mission of promoting the free
+distribution of electronic works, by using or distributing this work
+(or any other work associated in any way with the phrase “Project
+Gutenberg”), you agree to comply with all the terms of the Full
+Project Gutenberg™ License available with this file or online at
+www.gutenberg.org/license.
+
+Section 1. General Terms of Use and Redistributing Project Gutenberg™
+electronic works
+
+1.A. By reading or using any part of this Project Gutenberg™
+electronic work, you indicate that you have read, understand, agree to
+and accept all the terms of this license and intellectual property
+(trademark/copyright) agreement. If you do not agree to abide by all
+the terms of this agreement, you must cease using and return or
+destroy all copies of Project Gutenberg™ electronic works in your
+possession. If you paid a fee for obtaining a copy of or access to a
+Project Gutenberg™ electronic work and you do not agree to be bound
+by the terms of this agreement, you may obtain a refund from the person
+or entity to whom you paid the fee as set forth in paragraph 1.E.8.
+
+1.B. “Project Gutenberg” is a registered trademark. It may only be
+used on or associated in any way with an electronic work by people who
+agree to be bound by the terms of this agreement. There are a few
+things that you can do with most Project Gutenberg™ electronic works
+even without complying with the full terms of this agreement. See
+paragraph 1.C below. There are a lot of things you can do with Project
+Gutenberg™ electronic works if you follow the terms of this
+agreement and help preserve free future access to Project Gutenberg™
+electronic works. See paragraph 1.E below.
+
+1.C. The Project Gutenberg Literary Archive Foundation (“the
+Foundation” or PGLAF), owns a compilation copyright in the collection
+of Project Gutenberg™ electronic works. Nearly all the individual
+works in the collection are in the public domain in the United
+States. If an individual work is unprotected by copyright law in the
+United States and you are located in the United States, we do not
+claim a right to prevent you from copying, distributing, performing,
+displaying or creating derivative works based on the work as long as
+all references to Project Gutenberg are removed. Of course, we hope
+that you will support the Project Gutenberg™ mission of promoting
+free access to electronic works by freely sharing Project Gutenberg™
+works in compliance with the terms of this agreement for keeping the
+Project Gutenberg™ name associated with the work. You can easily
+comply with the terms of this agreement by keeping this work in the
+same format with its attached full Project Gutenberg™ License when
+you share it without charge with others.
+
+1.D. The copyright laws of the place where you are located also govern
+what you can do with this work. Copyright laws in most countries are
+in a constant state of change. If you are outside the United States,
+check the laws of your country in addition to the terms of this
+agreement before downloading, copying, displaying, performing,
+distributing or creating derivative works based on this work or any
+other Project Gutenberg™ work. The Foundation makes no
+representations concerning the copyright status of any work in any
+country other than the United States.
+
+1.E. Unless you have removed all references to Project Gutenberg:
+
+1.E.1. The following sentence, with active links to, or other
+immediate access to, the full Project Gutenberg™ License must appear
+prominently whenever any copy of a Project Gutenberg™ work (any work
+on which the phrase “Project Gutenberg” appears, or with which the
+phrase “Project Gutenberg” is associated) is accessed, displayed,
+performed, viewed, copied or distributed:
+
+    This eBook is for the use of anyone anywhere in the United States and most
+    other parts of the world at no cost and with almost no restrictions
+    whatsoever. You may copy it, give it away or re-use it under the terms
+    of the Project Gutenberg License included with this eBook or online
+    at www.gutenberg.org. If you
+    are not located in the United States, you will have to check the laws
+    of the country where you are located before using this eBook.
+  
+1.E.2. If an individual Project Gutenberg™ electronic work is
+derived from texts not protected by U.S. copyright law (does not
+contain a notice indicating that it is posted with permission of the
+copyright holder), the work can be copied and distributed to anyone in
+the United States without paying any fees or charges. If you are
+redistributing or providing access to a work with the phrase “Project
+Gutenberg” associated with or appearing on the work, you must comply
+either with the requirements of paragraphs 1.E.1 through 1.E.7 or
+obtain permission for the use of the work and the Project Gutenberg™
+trademark as set forth in paragraphs 1.E.8 or 1.E.9.
+
+1.E.3. If an individual Project Gutenberg™ electronic work is posted
+with the permission of the copyright holder, your use and distribution
+must comply with both paragraphs 1.E.1 through 1.E.7 and any
+additional terms imposed by the copyright holder. Additional terms
+will be linked to the Project Gutenberg™ License for all works
+posted with the permission of the copyright holder found at the
+beginning of this work.
+
+1.E.4. Do not unlink or detach or remove the full Project Gutenberg™
+License terms from this work, or any files containing a part of this
+work or any other work associated with Project Gutenberg™.
+
+1.E.5. Do not copy, display, perform, distribute or redistribute this
+electronic work, or any part of this electronic work, without
+prominently displaying the sentence set forth in paragraph 1.E.1 with
+active links or immediate access to the full terms of the Project
+Gutenberg™ License.
+
+1.E.6. You may convert to and distribute this work in any binary,
+compressed, marked up, nonproprietary or proprietary form, including
+any word processing or hypertext form. However, if you provide access
+to or distribute copies of a Project Gutenberg™ work in a format
+other than “Plain Vanilla ASCII” or other format used in the official
+version posted on the official Project Gutenberg™ website
+(www.gutenberg.org), you must, at no additional cost, fee or expense
+to the user, provide a copy, a means of exporting a copy, or a means
+of obtaining a copy upon request, of the work in its original “Plain
+Vanilla ASCII” or other form. Any alternate format must include the
+full Project Gutenberg™ License as specified in paragraph 1.E.1.
+
+1.E.7. Do not charge a fee for access to, viewing, displaying,
+performing, copying or distributing any Project Gutenberg™ works
+unless you comply with paragraph 1.E.8 or 1.E.9.
+
+1.E.8. You may charge a reasonable fee for copies of or providing
+access to or distributing Project Gutenberg™ electronic works
+provided that:
+
+    • You pay a royalty fee of 20% of the gross profits you derive from
+        the use of Project Gutenberg™ works calculated using the method
+        you already use to calculate your applicable taxes. The fee is owed
+        to the owner of the Project Gutenberg™ trademark, but he has
+        agreed to donate royalties under this paragraph to the Project
+        Gutenberg Literary Archive Foundation. Royalty payments must be paid
+        within 60 days following each date on which you prepare (or are
+        legally required to prepare) your periodic tax returns. Royalty
+        payments should be clearly marked as such and sent to the Project
+        Gutenberg Literary Archive Foundation at the address specified in
+        Section 4, “Information about donations to the Project Gutenberg
+        Literary Archive Foundation.”
+    
+    • You provide a full refund of any money paid by a user who notifies
+        you in writing (or by e-mail) within 30 days of receipt that s/he
+        does not agree to the terms of the full Project Gutenberg™
+        License. You must require such a user to return or destroy all
+        copies of the works possessed in a physical medium and discontinue
+        all use of and all access to other copies of Project Gutenberg™
+        works.
+    
+    • You provide, in accordance with paragraph 1.F.3, a full refund of
+        any money paid for a work or a replacement copy, if a defect in the
+        electronic work is discovered and reported to you within 90 days of
+        receipt of the work.
+    
+    • You comply with all other terms of this agreement for free
+        distribution of Project Gutenberg™ works.
+    
+
+1.E.9. If you wish to charge a fee or distribute a Project
+Gutenberg™ electronic work or group of works on different terms than
+are set forth in this agreement, you must obtain permission in writing
+from the Project Gutenberg Literary Archive Foundation, the manager of
+the Project Gutenberg™ trademark. Contact the Foundation as set
+forth in Section 3 below.
+
+1.F.
+
+1.F.1. Project Gutenberg volunteers and employees expend considerable
+effort to identify, do copyright research on, transcribe and proofread
+works not protected by U.S. copyright law in creating the Project
+Gutenberg™ collection. Despite these efforts, Project Gutenberg™
+electronic works, and the medium on which they may be stored, may
+contain “Defects,” such as, but not limited to, incomplete, inaccurate
+or corrupt data, transcription errors, a copyright or other
+intellectual property infringement, a defective or damaged disk or
+other medium, a computer virus, or computer codes that damage or
+cannot be read by your equipment.
+
+1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the “Right
+of Replacement or Refund” described in paragraph 1.F.3, the Project
+Gutenberg Literary Archive Foundation, the owner of the Project
+Gutenberg™ trademark, and any other party distributing a Project
+Gutenberg™ electronic work under this agreement, disclaim all
+liability to you for damages, costs and expenses, including legal
+fees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT
+LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE
+PROVIDED IN PARAGRAPH 1.F.3. YOU AGREE THAT THE FOUNDATION, THE
+TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE
+LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR
+INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a
+defect in this electronic work within 90 days of receiving it, you can
+receive a refund of the money (if any) you paid for it by sending a
+written explanation to the person you received the work from. If you
+received the work on a physical medium, you must return the medium
+with your written explanation. The person or entity that provided you
+with the defective work may elect to provide a replacement copy in
+lieu of a refund. If you received the work electronically, the person
+or entity providing it to you may choose to give you a second
+opportunity to receive the work electronically in lieu of a refund. If
+the second copy is also defective, you may demand a refund in writing
+without further opportunities to fix the problem.
+
+1.F.4. Except for the limited right of replacement or refund set forth
+in paragraph 1.F.3, this work is provided to you ‘AS-IS’, WITH NO
+OTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+LIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.
+
+1.F.5. Some states do not allow disclaimers of certain implied
+warranties or the exclusion or limitation of certain types of
+damages. If any disclaimer or limitation set forth in this agreement
+violates the law of the state applicable to this agreement, the
+agreement shall be interpreted to make the maximum disclaimer or
+limitation permitted by the applicable state law. The invalidity or
+unenforceability of any provision of this agreement shall not void the
+remaining provisions.
+
+1.F.6. INDEMNITY - You agree to indemnify and hold the Foundation, the
+trademark owner, any agent or employee of the Foundation, anyone
+providing copies of Project Gutenberg™ electronic works in
+accordance with this agreement, and any volunteers associated with the
+production, promotion and distribution of Project Gutenberg™
+electronic works, harmless from all liability, costs and expenses,
+including legal fees, that arise directly or indirectly from any of
+the following which you do or cause to occur: (a) distribution of this
+or any Project Gutenberg™ work, (b) alteration, modification, or
+additions or deletions to any Project Gutenberg™ work, and (c) any
+Defect you cause.
+
+Section 2. Information about the Mission of Project Gutenberg™
+
+Project Gutenberg™ is synonymous with the free distribution of
+electronic works in formats readable by the widest variety of
+computers including obsolete, old, middle-aged and new computers. It
+exists because of the efforts of hundreds of volunteers and donations
+from people in all walks of life.
+
+Volunteers and financial support to provide volunteers with the
+assistance they need are critical to reaching Project Gutenberg™’s
+goals and ensuring that the Project Gutenberg™ collection will
+remain freely available for generations to come. In 2001, the Project
+Gutenberg Literary Archive Foundation was created to provide a secure
+and permanent future for Project Gutenberg™ and future
+generations. To learn more about the Project Gutenberg Literary
+Archive Foundation and how your efforts and donations can help, see
+Sections 3 and 4 and the Foundation information page at www.gutenberg.org.
+
+Section 3. Information about the Project Gutenberg Literary Archive Foundation
+
+The Project Gutenberg Literary Archive Foundation is a non-profit
+501(c)(3) educational corporation organized under the laws of the
+state of Mississippi and granted tax exempt status by the Internal
+Revenue Service. The Foundation’s EIN or federal tax identification
+number is 64-6221541. Contributions to the Project Gutenberg Literary
+Archive Foundation are tax deductible to the full extent permitted by
+U.S. federal laws and your state’s laws.
+
+The Foundation’s business office is located at 809 North 1500 West,
+Salt Lake City, UT 84116, (801) 596-1887. Email contact links and up
+to date contact information can be found at the Foundation’s website
+and official page at www.gutenberg.org/contact
+
+Section 4. Information about Donations to the Project Gutenberg
+Literary Archive Foundation
+
+Project Gutenberg™ depends upon and cannot survive without widespread
+public support and donations to carry out its mission of
+increasing the number of public domain and licensed works that can be
+freely distributed in machine-readable form accessible by the widest
+array of equipment including outdated equipment. Many small donations
+($1 to $5,000) are particularly important to maintaining tax exempt
+status with the IRS.
+
+The Foundation is committed to complying with the laws regulating
+charities and charitable donations in all 50 states of the United
+States. Compliance requirements are not uniform and it takes a
+considerable effort, much paperwork and many fees to meet and keep up
+with these requirements. We do not solicit donations in locations
+where we have not received written confirmation of compliance. To SEND
+DONATIONS or determine the status of compliance for any particular state
+visit www.gutenberg.org/donate.
+
+While we cannot and do not solicit contributions from states where we
+have not met the solicitation requirements, we know of no prohibition
+against accepting unsolicited donations from donors in such states who
+approach us with offers to donate.
+
+International donations are gratefully accepted, but we cannot make
+any statements concerning tax treatment of donations received from
+outside the United States. U.S. laws alone swamp our small staff.
+
+Please check the Project Gutenberg web pages for current donation
+methods and addresses. Donations are accepted in a number of other
+ways including checks, online payments and credit card donations. To
+donate, please visit: www.gutenberg.org/donate.
+
+Section 5. General Information About Project Gutenberg™ electronic works
+
+Professor Michael S. Hart was the originator of the Project
+Gutenberg™ concept of a library of electronic works that could be
+freely shared with anyone. For forty years, he produced and
+distributed Project Gutenberg™ eBooks with only a loose network of
+volunteer support.
+
+Project Gutenberg™ eBooks are often created from several printed
+editions, all of which are confirmed as not protected by copyright in
+the U.S. unless a copyright notice is included. Thus, we do not
+necessarily keep eBooks in compliance with any particular paper
+edition.
+
+Most people start at our website which has the main PG search
+facility: www.gutenberg.org.
+
+This website includes information about Project Gutenberg™,
+including how to make donations to the Project Gutenberg Literary
+Archive Foundation, how to help produce our new eBooks, and how to
+subscribe to our email newsletter to hear about new eBooks.
+
+
diff --git a/Samples~/RAG/hamlet_project_gutenberg.txt.meta b/Samples~/RAG/hamlet_project_gutenberg.txt.meta
new file mode 100644
index 00000000..e10161ad
--- /dev/null
+++ b/Samples~/RAG/hamlet_project_gutenberg.txt.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 145dfa55295462fa4bc804a75d8ba9c1
+TextScriptImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Samples~/SimpleInteraction/TestDownload.cs b/Samples~/SimpleInteraction/TestDownload.cs
deleted file mode 100644
index 585814d1..00000000
--- a/Samples~/SimpleInteraction/TestDownload.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using UnityEngine;
-using LLMUnity;
-using UnityEngine.UI;
-using System.Threading.Tasks;
-using System.IO;
-
-namespace LLMUnitySamples
-{
-    public class TestDownload : MonoBehaviour
-    {
-        public InputField playerText;
-        public Scrollbar progressBar;
-        public Text progressText;
-        public Toggle overwriteToggle;
-
-        void Start()
-        {
-            playerText.onSubmit.AddListener(onInputFieldSubmit);
-        }
-
-        void SetProgress(float progress)
-        {
-            // Debug.Log(progress);
-            progressText.text = ((int)(progress * 100)).ToString() + "%";
-            progressBar.size = progress;
-        }
-
-        string path;
-        void onInputFieldSubmit(string message)
-        {
-            string url = message.Trim();
-            path = "/tmp/" + Path.GetFileName(url).Split("?")[0];
-            playerText.interactable = false;
-            Debug.Log(overwriteToggle.isOn);
-            _ = LLMUnitySetup.DownloadFile(
-                url, path, overwriteToggle.isOn,
-                CompleteCallback, SetProgress
-            );
-        }
-
-        public void CompleteCallback(string path)
-        {
-            Complete();
-        }
-
-        public void Complete()
-        {
-            playerText.interactable = true;
-            playerText.Select();
-            playerText.text = "";
-        }
-
-        public void CancelRequests()
-        {
-            LLMUnitySetup.CancelDownload(path);
-            Complete();
-        }
-    }
-}
diff --git a/Tests/Runtime/TestLLM.cs b/Tests/Runtime/TestLLM.cs
index 166c04f1..e1a2b73c 100644
--- a/Tests/Runtime/TestLLM.cs
+++ b/Tests/Runtime/TestLLM.cs
@@ -71,7 +71,6 @@ public void TestLoras()
 
     public class TestLLM
     {
-        protected static string modelUrl = "https://huggingface.co/Qwen/Qwen2-0.5B-Instruct-GGUF/resolve/main/qwen2-0_5b-instruct-q4_k_m.gguf?download=true";
         protected string modelNameLLManager;
 
         protected GameObject gameObject;
@@ -112,6 +111,10 @@ public virtual void SetParameters()
             {
                 reply2 = "To increase your meme production/output, you can try using various tools and techniques to create more engaging content";
             }
+            else if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer)
+            {
+                reply2 = "To increase your meme production/output, you can try using various tools and techniques. Here are some suggestions";
+            }
             else
             {
                 reply2 = "To increase your meme production/output, you can try the following strategies:\n\n1. Use a meme generator";
@@ -120,9 +123,14 @@ public virtual void SetParameters()
             tokens2 = 9;
         }
 
+        protected virtual string GetModelUrl()
+        {
+            return "https://huggingface.co/Qwen/Qwen2-0.5B-Instruct-GGUF/resolve/main/qwen2-0_5b-instruct-q4_k_m.gguf?download=true";
+        }
+
         public virtual async Task DownloadModels()
         {
-            modelNameLLManager = await LLMManager.DownloadModel(modelUrl);
+            modelNameLLManager = await LLMManager.DownloadModel(GetModelUrl());
         }
 
         [Test]
@@ -292,7 +300,7 @@ public class TestLLM_LLMManager_Load : TestLLM
         public override LLM CreateLLM()
         {
             LLM llm = gameObject.AddComponent<LLM>();
-            string filename = Path.GetFileName(modelUrl).Split("?")[0];
+            string filename = Path.GetFileName(GetModelUrl()).Split("?")[0];
             string sourcePath = Path.Combine(LLMUnitySetup.modelDownloadPath, filename);
             filename = LLMManager.LoadModel(sourcePath);
             llm.SetModel(filename);
@@ -308,7 +316,7 @@ public class TestLLM_StreamingAssets_Load : TestLLM
         public override LLM CreateLLM()
         {
             LLM llm = gameObject.AddComponent<LLM>();
-            string filename = Path.GetFileName(modelUrl).Split("?")[0];
+            string filename = Path.GetFileName(GetModelUrl()).Split("?")[0];
             string sourcePath = Path.Combine(LLMUnitySetup.modelDownloadPath, filename);
             loadPath = LLMUnitySetup.GetAssetPath(filename);
             if (!File.Exists(loadPath)) File.Copy(sourcePath, loadPath);
@@ -328,7 +336,7 @@ public class TestLLM_SetModel_Warning : TestLLM
         public override LLM CreateLLM()
         {
             LLM llm = gameObject.AddComponent<LLM>();
-            string filename = Path.GetFileName(modelUrl).Split("?")[0];
+            string filename = Path.GetFileName(GetModelUrl()).Split("?")[0];
             string loadPath = Path.Combine(LLMUnitySetup.modelDownloadPath, filename);
             llm.SetModel(loadPath);
             llm.parallelPrompts = 1;
@@ -400,7 +408,7 @@ public override async Task Tests()
 
         public void TestModelPaths()
         {
-            Assert.AreEqual(llm.model, Path.Combine(LLMUnitySetup.modelDownloadPath, Path.GetFileName(modelUrl).Split("?")[0]).Replace('\\', '/'));
+            Assert.AreEqual(llm.model, Path.Combine(LLMUnitySetup.modelDownloadPath, Path.GetFileName(GetModelUrl()).Split("?")[0]).Replace('\\', '/'));
             Assert.AreEqual(llm.lora, Path.Combine(LLMUnitySetup.modelDownloadPath, Path.GetFileName(loraUrl).Split("?")[0]).Replace('\\', '/'));
         }
 
diff --git a/Tests/Runtime/TestSearch.cs b/Tests/Runtime/TestSearch.cs
new file mode 100644
index 00000000..5a0872b3
--- /dev/null
+++ b/Tests/Runtime/TestSearch.cs
@@ -0,0 +1,700 @@
+using NUnit.Framework;
+using System.IO;
+using System.Threading.Tasks;
+using UnityEngine;
+using LLMUnity;
+using System;
+using UnityEngine.TestTools;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace LLMUnityTests
+{
+    public abstract class TestSearchable<T> where T : Searchable
+    {
+        protected string weather = "how is the weather today?";
+        protected string raining = "is it raining?";
+        protected string sometext = "something completely sometext";
+        protected float weatherRainingDiff = 0.2073563f;
+        protected float weatherSometextDiff = 0.4837922f;
+
+        protected string modelNameLLManager;
+        protected GameObject gameObject;
+        protected LLM llm;
+        public T search;
+        protected Exception error = null;
+
+        public TestSearchable()
+        {
+            Task task = Init();
+            task.Wait();
+        }
+
+        public virtual async Task Init()
+        {
+            await DownloadModels();
+            gameObject = new GameObject();
+            gameObject.SetActive(false);
+            llm = CreateLLM();
+            search = CreateSearch();
+            gameObject.SetActive(true);
+        }
+
+        public virtual LLM CreateLLM()
+        {
+            LLM llm = gameObject.AddComponent<LLM>();
+            llm.SetModel(modelNameLLManager);
+            llm.parallelPrompts = 1;
+            return llm;
+        }
+
+        public abstract T CreateSearch();
+
+        public virtual async Task DownloadModels()
+        {
+            modelNameLLManager = await LLMManager.DownloadModel(GetModelUrl());
+        }
+
+        protected virtual string GetModelUrl()
+        {
+            return "https://huggingface.co/CompendiumLabs/bge-small-en-v1.5-gguf/resolve/main/bge-small-en-v1.5-f16.gguf";
+        }
+
+        public static bool ApproxEqual(float x1, float x2)
+        {
+            float tolerance = (Application.platform == RuntimePlatform.OSXPlayer) ? 0.001f : 0.0001f;
+            return Mathf.Abs(x1 - x2) < tolerance;
+        }
+
+        [UnityTest]
+        public virtual IEnumerator RunTests()
+        {
+            Task task = RunTestsTask();
+            while (!task.IsCompleted) yield return null;
+            if (error != null)
+            {
+                Debug.LogError(error.ToString());
+                throw (error);
+            }
+        }
+
+        public virtual async Task RunTestsTask()
+        {
+            error = null;
+            try
+            {
+                await Tests();
+                llm.OnDestroy();
+            }
+            catch  (Exception e)
+            {
+                error = e;
+            }
+        }
+
+        public virtual async Task Tests()
+        {
+            await TestAdd();
+            await TestSearch();
+            await TestIncrementalSearch();
+            await TestSaveLoad();
+        }
+
+        public virtual async Task TestAdd()
+        {
+            void CheckCount(int[] nums)
+            {
+                int sum = 0;
+                for (int i = 0; i < nums.Length; i++)
+                {
+                    Assert.That(search.Count(i.ToString()) == nums[i]);
+                    sum += nums[i];
+                }
+                Assert.That(search.Count() == sum);
+            }
+
+            int key, num;
+            key = await search.Add(weather);
+            Assert.That(key == 0);
+            Assert.That(search.Get(key) == weather);
+            Assert.That(search.Count() == 1);
+            search.Remove(key);
+            Assert.That(search.Count() == 0);
+
+            key = await search.Add(weather);
+            Assert.That(key == 1);
+            key = await search.Add(raining);
+            Assert.That(key == 2);
+            key = await search.Add(sometext);
+            Assert.That(key == 3);
+            Assert.That(search.Count() == 3);
+            search.Clear();
+            Assert.That(search.Count() == 0);
+
+            key = await search.Add(weather, "0");
+            Assert.That(key == 0);
+            key = await search.Add(raining, "0");
+            Assert.That(key == 1);
+            key = await search.Add(weather, "1");
+            Assert.That(key == 2);
+            key = await search.Add(sometext, "1");
+            Assert.That(key == 3);
+            key = await search.Add(sometext, "2");
+            Assert.That(key == 4);
+            CheckCount(new int[] {2, 2, 1});
+            num = search.Remove(weather, "0");
+            Assert.That(num == 1);
+            CheckCount(new int[] {1, 2, 1});
+            num = search.Remove(weather, "1");
+            Assert.That(num == 1);
+            CheckCount(new int[] {1, 1, 1});
+            num = search.Remove(weather, "0");
+            Assert.That(num == 0);
+            CheckCount(new int[] {1, 1, 1});
+            num = search.Remove(raining, "0");
+            Assert.That(num == 1);
+            CheckCount(new int[] {0, 1, 1});
+            num = search.Remove(sometext, "1");
+            Assert.That(num == 1);
+            CheckCount(new int[] {0, 0, 1});
+            num = search.Remove(sometext, "2");
+            Assert.That(num == 1);
+            CheckCount(new int[] {0, 0, 0});
+
+            search.Clear();
+            Assert.That(search.Count() == 0);
+        }
+
+        public virtual async Task TestSearch()
+        {
+            string[] results;
+            float[] distances;
+
+            (results, distances) = await search.Search(weather, 1);
+            Assert.That(results.Length == 0);
+            Assert.That(distances.Length == 0);
+
+            await search.Add(weather);
+            await search.Add(raining);
+            await search.Add(sometext);
+
+            (results, distances) = await search.Search(weather, 2);
+            Assert.AreEqual(results.Length, 2);
+            Assert.AreEqual(distances.Length, 2);
+            Assert.AreEqual(results[0], weather);
+            Assert.AreEqual(results[1], raining);
+            Assert.That(ApproxEqual(distances[0], 0));
+            Assert.That(ApproxEqual(distances[1], weatherRainingDiff));
+
+            (results, distances) = await search.Search(raining, 2);
+            Assert.AreEqual(results.Length, 2);
+            Assert.AreEqual(distances.Length, 2);
+            Assert.AreEqual(results[0], raining);
+            Assert.AreEqual(results[1], weather);
+            Assert.That(ApproxEqual(distances[0], 0));
+            Assert.That(ApproxEqual(distances[1], weatherRainingDiff));
+
+            search.Clear();
+
+            await search.Add(weather, "0");
+            await search.Add(raining, "1");
+            await search.Add(sometext, "0");
+            await search.Add(sometext, "1");
+
+            (results, distances) = await search.Search(weather, 2, "0");
+            Assert.AreEqual(results.Length, 2);
+            Assert.AreEqual(distances.Length, 2);
+            Assert.AreEqual(results[0], weather);
+            Assert.AreEqual(results[1], sometext);
+            Assert.That(ApproxEqual(distances[0], 0));
+            Assert.That(ApproxEqual(distances[1], weatherSometextDiff));
+
+            (results, distances) = await search.Search(weather, 2, "0");
+            Assert.AreEqual(results.Length, 2);
+            Assert.AreEqual(distances.Length, 2);
+            Assert.AreEqual(results[0], weather);
+            Assert.AreEqual(results[1], sometext);
+            Assert.That(ApproxEqual(distances[0], 0));
+            Assert.That(ApproxEqual(distances[1], weatherSometextDiff));
+
+            (results, distances) = await search.Search(weather, 2, "1");
+            Assert.AreEqual(results.Length, 2);
+            Assert.AreEqual(distances.Length, 2);
+            Assert.AreEqual(results[0], raining);
+            Assert.AreEqual(results[1], sometext);
+            Assert.That(ApproxEqual(distances[1], weatherSometextDiff));
+
+            (results, distances) = await search.Search(weather, 3, "1");
+            Assert.AreEqual(results.Length, 2);
+            Assert.AreEqual(distances.Length, 2);
+            Assert.AreEqual(results[0], raining);
+            Assert.AreEqual(results[1], sometext);
+            Assert.That(ApproxEqual(distances[1], weatherSometextDiff));
+            search.Clear();
+        }
+
+        public async Task TestIncrementalSearch()
+        {
+            string[] results;
+            float[] distances;
+            bool completed;
+
+            int searchKey = await search.IncrementalSearch(weather);
+            (results, distances, completed) = search.IncrementalFetch(searchKey, 1);
+            Assert.That(searchKey == 0);
+            Assert.That(results.Length == 0);
+            Assert.That(distances.Length == 0);
+            Assert.That(completed);
+            search.Clear();
+
+            await search.Add(weather);
+            await search.Add(raining);
+            await search.Add(sometext);
+
+            searchKey = await search.IncrementalSearch(weather);
+            (results, distances, completed) = search.IncrementalFetch(searchKey, 1);
+            Assert.That(searchKey == 0);
+            Assert.That(results.Length == 1);
+            Assert.That(distances.Length == 1);
+            Assert.AreEqual(results[0], weather);
+            Assert.That(ApproxEqual(distances[0], 0));
+            Assert.That(!completed);
+
+            (results, distances, completed) = search.IncrementalFetch(searchKey, 2);
+            Assert.That(results.Length == 2);
+            Assert.That(distances.Length == 2);
+            Assert.AreEqual(results[0], raining);
+            Assert.AreEqual(results[1], sometext);
+            Assert.That(ApproxEqual(distances[0], weatherRainingDiff));
+            Assert.That(ApproxEqual(distances[1], weatherSometextDiff));
+            Assert.That(completed);
+
+            searchKey = await search.IncrementalSearch(weather);
+            (results, distances, completed) = search.IncrementalFetch(searchKey, 2);
+            Assert.That(searchKey == 1);
+            Assert.That(results.Length == 2);
+            Assert.That(distances.Length == 2);
+            Assert.AreEqual(results[0], weather);
+            Assert.AreEqual(results[1], raining);
+            Assert.That(ApproxEqual(distances[0], 0));
+            Assert.That(ApproxEqual(distances[1], weatherRainingDiff));
+            Assert.That(!completed);
+
+            search.IncrementalSearchComplete(searchKey);
+            search.Clear();
+
+            await search.Add(weather, "0");
+            await search.Add(raining, "1");
+            await search.Add(sometext, "0");
+            await search.Add(sometext, "1");
+
+            searchKey = await search.IncrementalSearch(weather, "0");
+            (results, distances, completed) = search.IncrementalFetch(searchKey, 2);
+            Assert.That(searchKey == 0);
+            Assert.AreEqual(results.Length, 2);
+            Assert.AreEqual(distances.Length, 2);
+            Assert.AreEqual(results[0], weather);
+            Assert.AreEqual(results[1], sometext);
+            Assert.That(ApproxEqual(distances[0], 0));
+            Assert.That(ApproxEqual(distances[1], weatherSometextDiff));
+            Assert.That(completed);
+
+            searchKey = await search.IncrementalSearch(weather, "0");
+            (results, distances, completed) = search.IncrementalFetch(searchKey, 2);
+            Assert.That(searchKey == 1);
+            Assert.AreEqual(results.Length, 2);
+            Assert.AreEqual(distances.Length, 2);
+            Assert.AreEqual(results[0], weather);
+            Assert.AreEqual(results[1], sometext);
+            Assert.That(ApproxEqual(distances[0], 0));
+            Assert.That(ApproxEqual(distances[1], weatherSometextDiff));
+            Assert.That(completed);
+
+            searchKey = await search.IncrementalSearch(weather, "1");
+            (results, distances, completed) = search.IncrementalFetch(searchKey, 1);
+            Assert.That(searchKey == 2);
+            Assert.AreEqual(results.Length, 1);
+            Assert.AreEqual(distances.Length, 1);
+            Assert.AreEqual(results[0], raining);
+            Assert.That(!completed);
+
+            (results, distances, completed) = search.IncrementalFetch(searchKey, 1);
+            Assert.AreEqual(results.Length, 1);
+            Assert.AreEqual(distances.Length, 1);
+            Assert.AreEqual(results[0], sometext);
+            Assert.That(ApproxEqual(distances[0], weatherSometextDiff));
+            Assert.That(completed);
+
+            searchKey = await search.IncrementalSearch(weather, "1");
+            (results, distances, completed) = search.IncrementalFetch(searchKey, 3);
+            Assert.That(searchKey == 3);
+            Assert.AreEqual(results.Length, 2);
+            Assert.AreEqual(distances.Length, 2);
+            Assert.AreEqual(results[0], raining);
+            Assert.AreEqual(results[1], sometext);
+            Assert.That(ApproxEqual(distances[1], weatherSometextDiff));
+            Assert.That(completed);
+            search.Clear();
+        }
+
+        public virtual async Task TestSaveLoad()
+        {
+            string path = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
+            string[] results;
+            float[] distances;
+
+            await search.Add(weather);
+            await search.Add(raining);
+            await search.Add(sometext);
+            search.Save(path);
+
+            search.Clear();
+            await search.Load(path);
+            File.Delete(path);
+
+            Assert.That(search.Count() == 3);
+            Assert.That(search.Get(0) == weather);
+            Assert.That(search.Get(1) == raining);
+            Assert.That(search.Get(2) == sometext);
+
+            (results, distances) = await search.Search(raining, 2);
+            Assert.AreEqual(results[0], raining);
+            Assert.AreEqual(results[1], weather);
+            Assert.That(ApproxEqual(distances[0], 0));
+            Assert.That(ApproxEqual(distances[1], weatherRainingDiff));
+
+            search.Clear();
+
+            await search.Add(weather, "0");
+            await search.Add(raining, "1");
+            await search.Add(sometext, "0");
+            await search.Add(sometext, "1");
+            search.Save(path);
+
+            search.Clear();
+            await search.Load(path);
+            File.Delete(path);
+
+            Assert.That(search.Count() == 4);
+            Assert.That(search.Count("0") == 2);
+            Assert.That(search.Count("1") == 2);
+            Assert.That(search.Get(0) == weather);
+            Assert.That(search.Get(1) == raining);
+            Assert.That(search.Get(2) == sometext);
+            Assert.That(search.Get(3) == sometext);
+
+            (results, distances) = await search.Search(raining, 2, "0");
+            Assert.AreEqual(results[0], weather);
+            Assert.AreEqual(results[1], sometext);
+            Assert.That(ApproxEqual(distances[0], weatherRainingDiff));
+
+            search.Clear();
+        }
+    }
+
+    public abstract class TestSearchMethod<T> : TestSearchable<T> where T : SearchMethod
+    {
+        public override T CreateSearch()
+        {
+            T search = gameObject.AddComponent<T>();
+            search.SetLLM(llm);
+            return search;
+        }
+
+        public override async Task Tests()
+        {
+            await base.Tests();
+            await TestEncode();
+            await TestSimilarity();
+            await TestSearchFromList();
+        }
+
+        public async Task TestEncode()
+        {
+            float[] encoding = await search.Encode(weather);
+            Assert.That(ApproxEqual(encoding[0], -0.02910374f));
+            Assert.That(ApproxEqual(encoding[383], 0.01764517f));
+        }
+
+        public async Task TestSimilarity()
+        {
+            float[] sentence1 = await search.Encode(weather);
+            float[] sentence2 = await search.Encode(raining);
+            float similarity = SimpleSearch.DotProduct(sentence1, sentence2);
+            float distance = SimpleSearch.InverseDotProduct(sentence1, sentence2);
+            Assert.That(ApproxEqual(similarity, 1 - weatherRainingDiff));
+            Assert.That(ApproxEqual(distance, weatherRainingDiff));
+        }
+
+        public async Task TestSearchFromList()
+        {
+            (string[] results, float[] distances) = await search.SearchFromList(weather, new string[] {sometext, raining});
+            Assert.AreEqual(results.Length, 2);
+            Assert.AreEqual(distances.Length, 2);
+            Assert.AreEqual(results[0], raining);
+            Assert.AreEqual(results[1], sometext);
+            Assert.That(ApproxEqual(distances[0], weatherRainingDiff));
+            Assert.That(ApproxEqual(distances[1], weatherSometextDiff));
+        }
+    }
+
+    public class TestSimpleSearch : TestSearchMethod<SimpleSearch> {}
+
+    public class TestDBSearch : TestSearchMethod<DBSearch> {}
+
+    public abstract class TestSplitter<T> : TestSearchable<T> where T : Chunking
+    {
+        public override T CreateSearch()
+        {
+            T search = gameObject.AddComponent<T>();
+            DBSearch searchMethod = gameObject.AddComponent<DBSearch>();
+            searchMethod.SetLLM(llm);
+            search.SetSearch(searchMethod);
+            return search;
+        }
+
+        public static (string, List<(int, int)>) GenerateText(int length)
+        {
+            System.Random random = new System.Random();
+            char[] characters = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
+
+            char[] generatedText = new char[length];
+            List<(int, int)> indices = new List<(int, int)>();
+            bool delimited = false;
+            bool seenChar = false;
+            int preI = 0;
+            for (int i = 0; i < length; i++)
+            {
+                int charType = random.Next(0, 20);
+                if (charType == 0)
+                {
+                    generatedText[i] = SentenceSplitter.DefaultDelimiters[random.Next(SentenceSplitter.DefaultDelimiters.Length)];
+                    delimited = seenChar && true;
+                }
+                else if (charType < 3)
+                {
+                    generatedText[i] = ' ';
+                }
+                else
+                {
+                    generatedText[i] = characters[random.Next(characters.Length)];
+                    if (delimited)
+                    {
+                        indices.Add((preI, i - 1));
+                        preI = i;
+                        delimited = false;
+                    }
+                    seenChar = true;
+                }
+            }
+            indices.Add((preI, length - 1));
+            return (new string(generatedText), indices);
+        }
+
+        public override async Task Tests()
+        {
+            await base.Tests();
+            await TestProperSplit();
+        }
+
+        public async Task TestProperSplit()
+        {
+            for (int length = 50; length <= 500; length += 50)
+            {
+                (string randomText, _) = GenerateText(length);
+                List<(int, int)> indices = await search.Split(randomText);
+                int currIndex = 0;
+                foreach ((int startIndex, int endIndex) in indices)
+                {
+                    Assert.AreEqual(currIndex, startIndex);
+                    currIndex = endIndex + 1;
+                }
+                Assert.AreEqual(currIndex, length);
+                int key = await search.Add(randomText);
+                Assert.AreEqual(search.Get(key), randomText);
+            }
+        }
+    }
+
+    public class TestTokenSplitter : TestSplitter<TokenSplitter> {}
+
+    public class TestWordSplitter : TestSplitter<WordSplitter>
+    {
+        public override async Task Tests()
+        {
+            await base.Tests();
+            await TestSplit();
+        }
+
+        public async Task TestSplit()
+        {
+            System.Random random = new System.Random();
+            char[] characters = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
+            char[] boundary = "       .,!".ToCharArray();
+            int w = 0;
+            for (int numSplits = 0; numSplits < 10; numSplits++)
+            {
+                List<string> splits = new List<string> {};
+                for (int splitNr = 0; splitNr < numSplits; splitNr++)
+                {
+                    int numWords = search.numWords;
+                    if (splitNr == numSplits - 1) numWords -= random.Next(search.numWords);
+
+                    string split = "";
+                    for (int wi = 0; wi < search.numWords; wi++)
+                    {
+                        split += "w" + characters[w++ % characters.Length] + boundary[random.Next(boundary.Length)];
+                    }
+                    splits.Add(split.TrimEnd());
+                }
+
+                string text = String.Join(" ", splits);
+                List<(int, int)> indices = await search.Split(text);
+                for (int i = 0; i < indices.Count; i++)
+                {
+                    (int startIndex, int endIndex) = indices[i];
+                    string splitPred = text.Substring(startIndex, endIndex - startIndex + 1);
+                    if (i != indices.Count - 1) splitPred = splitPred.Substring(0, splitPred.Length - 1);
+                    Assert.AreEqual(splitPred, splits[i]);
+                }
+            }
+        }
+    }
+
+    public class TestSentenceSplitter : TestSplitter<SentenceSplitter>
+    {
+        public override async Task Tests()
+        {
+            await base.Tests();
+            await TestSplit();
+        }
+
+        public async Task TestSplit()
+        {
+            async Task<string[]> SplitSentences(string text)
+            {
+                List<(int, int)> indices = await search.Split(text);
+                List<string> sentences = new List<string>();
+                foreach ((int startIndex, int endIndex) in indices) sentences.Add(text.Substring(startIndex, endIndex - startIndex + 1));
+                return sentences.ToArray();
+            }
+
+            string[] sentences = new string[]
+            {
+                "hi.",
+                "how are you today?",
+                "the weather is nice!",
+                "perfect"
+            };
+            string text;
+            string[] sentencesBack, sentencesGT;
+            int key;
+
+            sentencesGT = (string[])sentences.Clone();
+            text = String.Join("", sentencesGT);
+            sentencesBack = await SplitSentences(text);
+            Assert.AreEqual(sentencesBack, sentencesGT);
+            key = await search.Add(text);
+            Assert.AreEqual(search.Get(key), text);
+
+            sentencesGT = (string[])sentences.Clone();
+            sentencesGT[0] = "    " + sentencesGT[0] + "   ";
+            sentencesGT[1] += " ; ";
+            sentencesGT[2] += "....  ";
+            sentencesGT[3] += "  ?";
+            text = String.Join("", sentencesGT);
+            sentencesBack = await SplitSentences(text);
+            Assert.AreEqual(sentencesBack, sentencesGT);
+            key = await search.Add(text);
+            Assert.AreEqual(search.Get(key), text);
+
+            for (int length = 10; length <= 100; length += 10)
+            {
+                (string randomText, List<(int, int)> indicesGT) = GenerateText(length);
+                List<(int, int)> indices = await search.Split(randomText);
+                Assert.AreEqual(indices.Count, indicesGT.Count);
+                Assert.AreEqual(indices, indicesGT);
+                key = await search.Add(randomText);
+                Assert.AreEqual(search.Get(key), randomText);
+            }
+
+            search.Clear();
+        }
+    }
+
+    public abstract class TestRAG : TestSearchable<RAG>
+    {
+        public override RAG CreateSearch()
+        {
+            RAG rag = gameObject.AddComponent<RAG>();
+            rag.Init(GetSearchMethod(), GetChunkingMethod(), llm);
+            return rag;
+        }
+
+        public abstract SearchMethods GetSearchMethod();
+        public abstract ChunkingMethods GetChunkingMethod();
+    }
+
+    public class TestRAG_SimpleSearch_NoChunking : TestRAG
+    {
+        public override SearchMethods GetSearchMethod() { return SearchMethods.SimpleSearch; }
+        public override ChunkingMethods GetChunkingMethod() { return ChunkingMethods.NoChunking; }
+    }
+
+    public class TestRAG_DBSearch_NoChunking : TestRAG
+    {
+        public override SearchMethods GetSearchMethod() { return SearchMethods.DBSearch; }
+        public override ChunkingMethods GetChunkingMethod() { return ChunkingMethods.NoChunking; }
+    }
+
+    public class TestRAG_SimpleSearch_WordSplitter : TestRAG
+    {
+        public override SearchMethods GetSearchMethod() { return SearchMethods.SimpleSearch; }
+        public override ChunkingMethods GetChunkingMethod() { return ChunkingMethods.TokenSplitter; }
+    }
+
+    public class TestRAG_DBSearch_TokenSplitter : TestRAG
+    {
+        public override SearchMethods GetSearchMethod() { return SearchMethods.DBSearch; }
+        public override ChunkingMethods GetChunkingMethod() { return ChunkingMethods.TokenSplitter; }
+    }
+
+    public abstract class TestRAG_Chunking : TestRAG
+    {
+        public override async Task TestSearch()
+        {
+            await base.TestSearch();
+
+            string[] results;
+            float[] distances;
+
+            await search.Add(weather + raining);
+            await search.Add(sometext);
+
+            search.ReturnChunks(false);
+            (results, distances) = await search.Search(weather, 1);
+            Assert.That(results.Length == 1);
+            Assert.That(distances.Length == 1);
+            Assert.AreEqual(results[0], weather + raining);
+
+            search.ReturnChunks(true);
+            (results, distances) = await search.Search(weather, 1);
+            Assert.That(results.Length == 1);
+            Assert.That(distances.Length == 1);
+            Assert.AreEqual(results[0], weather);
+            search.Clear();
+        }
+    }
+
+    public class TestRAG_DBSearch_SentenceSplitter : TestRAG_Chunking
+    {
+        public override SearchMethods GetSearchMethod() { return SearchMethods.DBSearch; }
+        public override ChunkingMethods GetChunkingMethod() { return ChunkingMethods.SentenceSplitter; }
+    }
+
+    public class TestRAG_SimpleSearch_SentenceSplitter : TestRAG_Chunking
+    {
+        public override SearchMethods GetSearchMethod() { return SearchMethods.SimpleSearch; }
+        public override ChunkingMethods GetChunkingMethod() { return ChunkingMethods.SentenceSplitter; }
+    }
+}
diff --git a/Tests/Runtime/TestSearch.cs.meta b/Tests/Runtime/TestSearch.cs.meta
new file mode 100644
index 00000000..e59b5748
--- /dev/null
+++ b/Tests/Runtime/TestSearch.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a180f8b149e7fa4b2bf3ee216dd1a261
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Third Party Notices.md b/Third Party Notices.md
index f3b5d13d..ff702a4f 100644
--- a/Third Party Notices.md	
+++ b/Third Party Notices.md	
@@ -20,6 +20,14 @@ Origin: [link](https://github.com/Mozilla-Ocho/llamafile)<br>
 License Type: "Apache 2.0"<br>
 License: [link](https://github.com/Mozilla-Ocho/llamafile/blob/main/LICENSE)
 
+### USearch
+
+Developer: Unum Cloud<br>
+Origin: [link](https://github.com/unum-cloud/usearch)<br>
+License Type: "Apache 2.0"<br>
+License: [link](https://github.com/unum-cloud/usearch/blob/main/LICENSE)<br>
+Modifications: [link](ThirdParty/usearch/README.md)
+
 ---
 
 ## Models
@@ -98,16 +106,66 @@ Quantization: [link](https://huggingface.co/Qwen/Qwen2-0.5B-Instruct-GGUF)<br>
 License Type: "Apache 2.0"<br>
 License: [link](https://huggingface.co/Qwen/Qwen2-0.5B-Instruct-GGUF/blob/main/LICENSE)
 
----
+<br>
+
+### BAAI/bge-large-en-v1.5
+
+Developer: BAAI<br>
+Origin: [link](https://huggingface.co/BAAI/bge-large-en-v1.5)<br>
+License Type: "MIT"<br>
+License: [link](https://huggingface.co/BAAI/bge-large-en-v1.5)
+
+##### modified by: CompendiumLabs/bge-large-en-v1.5-gguf
+
+Developer: Compendium Labs<br>
+Origin: [link](https://huggingface.co/CompendiumLabs/bge-large-en-v1.5-gguf)<br>
+License Type: "MIT"<br>
+License: [link](https://huggingface.co/CompendiumLabs/bge-large-en-v1.5-gguf)
+
+<br>
+
+### BAAI/bge-base-en-v1.5
+
+Developer: BAAI<br>
+Origin: [link](https://huggingface.co/BAAI/bge-base-en-v1.5)<br>
+License Type: "MIT"<br>
+License: [link](https://huggingface.co/BAAI/bge-base-en-v1.5)
+
+##### modified by: CompendiumLabs/bge-base-en-v1.5-gguf
+
+Developer: Compendium Labs<br>
+Origin: [link](https://huggingface.co/CompendiumLabs/bge-base-en-v1.5-gguf)<br>
+License Type: "MIT"<br>
+License: [link](https://huggingface.co/CompendiumLabs/bge-base-en-v1.5-gguf)
 
-## Testing
+<br>
+
+### BAAI/bge-small-en-v1.5
+
+Developer: BAAI<br>
+Origin: [link](https://huggingface.co/BAAI/bge-small-en-v1.5)<br>
+License Type: "MIT"<br>
+License: [link](https://huggingface.co/BAAI/bge-small-en-v1.5)
 
-The following model is used for testing purposes:
+##### modified by: CompendiumLabs/bge-small-en-v1.5-gguf
+
+Developer: Compendium Labs<br>
+Origin: [link](https://huggingface.co/CompendiumLabs/bge-small-en-v1.5-gguf)<br>
+License Type: "MIT"<br>
+License: [link](https://huggingface.co/CompendiumLabs/bge-small-en-v1.5-gguf)
+
+<br>
+
+### sentence-transformers/all-MiniLM-L12-v2
+
+Developer: Sentence Transformers<br>
+Origin: [link](https://huggingface.co/sentence-transformers/all-MiniLM-L12-v2)<br>
+License Type: "Apache 2.0"<br>
+License: [link](https://huggingface.co/sentence-transformers/all-MiniLM-L12-v2)
 
-### BEE-spoke-data/smol_llama-220M-openhermes
+##### modified by: leliuga/all-MiniLM-L12-v2-GGUF
 
-Developer: BEEspoke Data<br>
-Origin: [link](https://huggingface.co/BEE-spoke-data/smol_llama-220M-openhermes)<br>
-Quantization: [link](https://huggingface.co/afrideva/smol_llama-220M-openhermes-GGUF)<br>
+Developer: Leliuga<br>
+Origin: [link](https://huggingface.co/leliuga/all-MiniLM-L12-v2-GGUF)<br>
 License Type: "Apache 2.0"<br>
-License: [link](https://huggingface.co/BEE-spoke-data/smol_llama-220M-openhermes)
+License: [link](https://huggingface.co/leliuga/all-MiniLM-L12-v2-GGUF)
diff --git a/ThirdParty.meta b/ThirdParty.meta
new file mode 100644
index 00000000..61b2f4b6
--- /dev/null
+++ b/ThirdParty.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: cdaa3e55ae35be443aa985e442e3f4ff
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/ThirdParty/usearch.meta b/ThirdParty/usearch.meta
new file mode 100644
index 00000000..a2a8b83c
--- /dev/null
+++ b/ThirdParty/usearch.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 47164dbfa5f37148a85f10f600e52819
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/package.json b/package.json
index 7e752c3a..49a81c0e 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,7 @@
     },
     {
       "displayName": "KnowledgeBaseGame",
-      "description": "Simple detective game using a knowledge base to provide information to the LLM.\n**Requires installation of the RAGSearchUnity package (from UndreamAI)**",
+      "description": "Simple detective game using a knowledge base to provide information to the LLM.",
       "path": "Samples~/KnowledgeBaseGame"
     },
     {
@@ -49,6 +49,11 @@
       "displayName": "AndroidDemo",
       "description": "Example Android app with an initial screen with model download progress",
       "path": "Samples~/AndroidDemo"
+    },
+    {
+      "displayName": "RAG",
+      "description": "Semantic search using a Retrieval Augmented Generation (RAG) system. Includes example using a RAG to feed information to a LLM.",
+      "path": "Samples~/RAG"
     }
    ],
    "author": {