mindcraft


Namemindcraft JSON
Version 0.2.4 PyPI version JSON
download
home_pagehttps://github.com/josejuanmartinez/mindcraft
SummaryMindcraft: an LLM-based engine for creating real NPCs. Empowered by Hugging Face, quantized LLMs with AWQ (thanks @TheBloke) and vLLM. It follows a RAG approach with chunk or sentence splitting, and a vector store. Right now, ChromaDB is the supported Vector Store and chunk splitting using `tiktoken` or sentence splitting using `spacy` are available.
upload_time2024-01-17 12:40:17
maintainer
docs_urlNone
authorJuan.Martinez
requires_python>=3.10.0
licenseMIT
keywords nlp llm npc conversations videogames
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <p align="center">
<img width="20%" src="https://github.com/josejuanmartinez/mindcraft/assets/36634572/0ef83288-9e53-444d-baa0-2c61b0fc26ca" alt="mindcraft"/>
</p>

# MindCraft
The open-source NLP library to craft the minds of your NPC characters for your video games.

Requires Python 3.10 or higher.

It includes the following features:

- Text generation using LLMs
- Motivations, personality, personal goals
- Knowledge and awareness about the world (RAG)
- Short and Long-term memory (RAG)
- Conversational styles
- Supervised finetuning by human feedback (SFT)
- Integration with vLLM for **fast inference** and **streaming** locally, remotelly or in Docker. 
- Usage of quantized AWQ models
- Integration with API and RPC (to come!)

## Create a World from a book
```python
from mindcraft.infra.engine.llm_types import LLMType
from mindcraft.infra.vectorstore.stores_types import StoresTypes
from mindcraft.infra.embeddings.embeddings_types import EmbeddingsTypes
from mindcraft.lore.world import World

world = World(world_name="Middle Earth from the Lord of the Rings",
              embeddings=EmbeddingsTypes.MINILM,
              store_type=StoresTypes.CHROMA,
              llm_type=LLMType.YI_6B_AWQ,
              fast=False,      # <--- fast=True to switch on vLLM
              remote=False,    # <--- remote=True to use a remote vLLM server
              streaming=True) # <--- streaming=True to use vLLM streaming
```

Now we use some book to carry out chunk splitting and add it to our favourite Vector Database (in our case, ChromaDB)
```python
from mindcraft.infra.splitters.text_splitters_types import TextSplitterTypes

world.book_to_world(book_path="/content/lotr1.txt",
                    text_splitter=TextSplitterTypes.SENTENCE_SPLITTER,
                    max_units=3,
                    overlap=1,
                    encoding='utf-8')
```

## Query the lore of the world
Once a world has been created and populated with lore, query the lore known by NPCs by doing:
```python
results = world.get_lore("What do you think about the Rings of Power?", num_results=5, min_similarity=0.95)
for i, d in enumerate(results.documents):
    print(f"SENTENCE {i}:\n{d}")
    print()
```

## Instantiate an NPC in a world
Once a world has been created and populated with lore, instantiate an NPC in it by doing:

```python
from mindcraft.features.motivation import Motivation
from mindcraft.features.personality import Personality
from mindcraft.features.mood import Mood

from mindcraft.mind.npc import NPC

name = "Galadriel"
description = "The Elven Queen of Lothlorien, bearer of Nenya, wife to Celeborn"
personalities = [Personality(x) for x in ['fair', 'mighty', 'wise', 'carying', 'kind']]
motivations = [Motivation(x) for x in ['Destroying the Evil', 'Protecting Middle Earth', 'Travelling West']]
mood = Mood('worried')

galadriel = NPC(name,
                description,
                personalities,
                motivations,
                mood,
                StoresTypes.CHROMA,
                EmbeddingsTypes.MINILM)

galadriel.add_npc_to_world()
```

# Ask questions to the NPC
We get an iterator for the responses, to allow inference in streaming way.
```python
answer_iter = galadriel.react_to("What do you think about the Rings of Power",
                               min_similarity=0.85,
                               ltm_num_results=3,
                               world_num_results=7,
                               max_tokens=600)
```

So your answers will be in the iterator, don't forget to loop through it!
```
for answer in answer_iter:
    print(answer)
```

### Example of answer using Zephyr 7B quantized to 4b
```Alas, my dear friend, the Rings of Power are a perilous burden that should not be wielded by those of mortal race. They possess a sinister force that overcomes the spirit, enslaving their very soul. I have observed their destructive potential in Eregion long ago, where many Elven-rings were created, each infused with its own unique potency. Some more potent than others, and often, they seem to have a propensity to gravitate towards the unsuspecting. In light of our shared concern for the wellbeing of Middle Earth, I implore you to heed my words; let us not succumb to the allure of these fateful rings, lest they consume us entirely.```

## Creating custom Supervised Finetuning datasets for NPCs
There are two loops integrated in the framework which allow you to create your own datasets.
1. `NPC.extract_conversational_styles_from_world`: Retrieving conversations from the world and tagging the question and mood yourself
2. `NPC.extract_conversational_styles_talking_to_user`: Creates conversations by talking to you

### Supervised Finetuning
You can create  your own datasets with supervised finetuning,
accepting or rejecting the interactions. As a result, you will come up
with a csv of interactions you can use to train or finetune your own models.

```csv
name||mood||question||answer
Galadriel||default||Good night, Galadriel!||'Good night, my friends! '\nsaid Galadriel. '\nSleep in peace!
Galadriel||grave||why he could say that?||....`He would be rash indeed that said that thing,' said Galadriel gravely.
```

## LLM integrated
### Quantized
- TheBloke/mistral_7b_norobots-AWQ
- TheBloke/zephyr-7B-beta-AWQ
- TheBloke/notus-7B-v1-AWQ
- TheBloke/Starling-LM-7B-alpha-AWQ
- TheBloke/Yi-6B-AWQ
- TheBloke/dragon-yi-6B-v0-AWQ
### Unquantized
- microsoft/phi-2
- stabilityai/stablelm-zephyr-3b

## Embeddings for RAG
- [sentence-transformers/all-MiniLM-L6-v2](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2)

## CUDA and Torch in WINDOWS
If you are running on Windows on a machine with a GPU, and you get a message about not being able to find 
your gpu, you need to configure CUDA for Windows.

1. Go to [CUDA installation webpage](https://developer.nvidia.com/cuda-downloads).
2. Select your Windows version and specifics.
3. Download and install
4. Uninstall torch (`pip uninstall torch`)
5a. Go to requirements.txt, comment the line after LINUX for torch and uncomment the line after WINDOWS
5b. Alternatively you can just run this command:
```
pip3 install torch -i https://download.pytorch.org/whl/cu121
```

You torch on windows CUDA should be working. To test it:
```python
import torch

if __name__ == "__main__":
    print(torch.cuda.is_available())
```


## vLLM
`vLLM` has been included for Fast Inference, in local, remote installations and Docker.

### Local Fast inference (Paged Attention)

To use fast-inference, just run add `fast=True` to your `World` object:
```python
world = World(world_name="Lord of the Rings",
              embeddings=EmbeddingsTypes.MINILM,
              store_type=StoresTypes.CHROMA,
              llm_type=LLMType.YI_6B_AWQ,
              fast=True) # <---- HERE
```

### Remote Fast Inference
To the previous `fast` parameter, add also `remote=True`
```python
world = World(world_name="Lord of the Rings",
              embeddings=EmbeddingsTypes.MINILM,
              store_type=StoresTypes.CHROMA,
              llm_type=LLMType.YI_6B_AWQ,
              fast=True,   # <---- HERE
              remote=True) # <---- HERE
```

### Streaming (only if remote!)
To the previous `fast` and `remote` parameters, add also `streaming=True`
```python
world = World(world_name="Lord of the Rings",
              embeddings=EmbeddingsTypes.MINILM,
              store_type=StoresTypes.CHROMA,
              llm_type=LLMType.YI_6B_AWQ,
              fast=True,   # <---- HERE
              remote=True,
              streaming=True) # <---- HERE
```

## Example data
- [Lord of the Rings](https://www.kaggle.com/datasets/ashishsinhaiitr/lord-of-the-rings-text)

## Notebooks
You can find notebooks in the `notebooks` folder of this project.

## Demo 1: Creating a World and an NPC
[Video](https://youtu.be/T-D1KVIuvjA)

## Architecture
<p align="center">
<img 
  width="50%"
  src="https://github.com/josejuanmartinez/mindcraft/assets/36634572/7778d4a4-6b25-4b1a-9b26-b1bfa9d94727" alt="mindcraft architecture"/>
</p>

## Tests
`python -m pytest tests/*`

## Header
<p align="center">
<img width="100%" src="https://github.com/josejuanmartinez/mindcraft/blob/main/galadriel.png" alt="galadriel"/>
</p>

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/josejuanmartinez/mindcraft",
    "name": "mindcraft",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.10.0",
    "maintainer_email": "",
    "keywords": "nlp,llm,npc,conversations,videogames",
    "author": "Juan.Martinez",
    "author_email": "jjmcarrascosa@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/49/70/9a970687303ad7e1c042f9dde5b3a24be591d088403407a453489a3b6c7d/mindcraft-0.2.4.tar.gz",
    "platform": null,
    "description": "<p align=\"center\">\r\n<img width=\"20%\" src=\"https://github.com/josejuanmartinez/mindcraft/assets/36634572/0ef83288-9e53-444d-baa0-2c61b0fc26ca\" alt=\"mindcraft\"/>\r\n</p>\r\n\r\n# MindCraft\r\nThe open-source NLP library to craft the minds of your NPC characters for your video games.\r\n\r\nRequires Python 3.10 or higher.\r\n\r\nIt includes the following features:\r\n\r\n- Text generation using LLMs\r\n- Motivations, personality, personal goals\r\n- Knowledge and awareness about the world (RAG)\r\n- Short and Long-term memory (RAG)\r\n- Conversational styles\r\n- Supervised finetuning by human feedback (SFT)\r\n- Integration with vLLM for **fast inference** and **streaming** locally, remotelly or in Docker. \r\n- Usage of quantized AWQ models\r\n- Integration with API and RPC (to come!)\r\n\r\n## Create a World from a book\r\n```python\r\nfrom mindcraft.infra.engine.llm_types import LLMType\r\nfrom mindcraft.infra.vectorstore.stores_types import StoresTypes\r\nfrom mindcraft.infra.embeddings.embeddings_types import EmbeddingsTypes\r\nfrom mindcraft.lore.world import World\r\n\r\nworld = World(world_name=\"Middle Earth from the Lord of the Rings\",\r\n              embeddings=EmbeddingsTypes.MINILM,\r\n              store_type=StoresTypes.CHROMA,\r\n              llm_type=LLMType.YI_6B_AWQ,\r\n              fast=False,      # <--- fast=True to switch on vLLM\r\n              remote=False,    # <--- remote=True to use a remote vLLM server\r\n              streaming=True) # <--- streaming=True to use vLLM streaming\r\n```\r\n\r\nNow we use some book to carry out chunk splitting and add it to our favourite Vector Database (in our case, ChromaDB)\r\n```python\r\nfrom mindcraft.infra.splitters.text_splitters_types import TextSplitterTypes\r\n\r\nworld.book_to_world(book_path=\"/content/lotr1.txt\",\r\n                    text_splitter=TextSplitterTypes.SENTENCE_SPLITTER,\r\n                    max_units=3,\r\n                    overlap=1,\r\n                    encoding='utf-8')\r\n```\r\n\r\n## Query the lore of the world\r\nOnce a world has been created and populated with lore, query the lore known by NPCs by doing:\r\n```python\r\nresults = world.get_lore(\"What do you think about the Rings of Power?\", num_results=5, min_similarity=0.95)\r\nfor i, d in enumerate(results.documents):\r\n    print(f\"SENTENCE {i}:\\n{d}\")\r\n    print()\r\n```\r\n\r\n## Instantiate an NPC in a world\r\nOnce a world has been created and populated with lore, instantiate an NPC in it by doing:\r\n\r\n```python\r\nfrom mindcraft.features.motivation import Motivation\r\nfrom mindcraft.features.personality import Personality\r\nfrom mindcraft.features.mood import Mood\r\n\r\nfrom mindcraft.mind.npc import NPC\r\n\r\nname = \"Galadriel\"\r\ndescription = \"The Elven Queen of Lothlorien, bearer of Nenya, wife to Celeborn\"\r\npersonalities = [Personality(x) for x in ['fair', 'mighty', 'wise', 'carying', 'kind']]\r\nmotivations = [Motivation(x) for x in ['Destroying the Evil', 'Protecting Middle Earth', 'Travelling West']]\r\nmood = Mood('worried')\r\n\r\ngaladriel = NPC(name,\r\n                description,\r\n                personalities,\r\n                motivations,\r\n                mood,\r\n                StoresTypes.CHROMA,\r\n                EmbeddingsTypes.MINILM)\r\n\r\ngaladriel.add_npc_to_world()\r\n```\r\n\r\n# Ask questions to the NPC\r\nWe get an iterator for the responses, to allow inference in streaming way.\r\n```python\r\nanswer_iter = galadriel.react_to(\"What do you think about the Rings of Power\",\r\n                               min_similarity=0.85,\r\n                               ltm_num_results=3,\r\n                               world_num_results=7,\r\n                               max_tokens=600)\r\n```\r\n\r\nSo your answers will be in the iterator, don't forget to loop through it!\r\n```\r\nfor answer in answer_iter:\r\n    print(answer)\r\n```\r\n\r\n### Example of answer using Zephyr 7B quantized to 4b\r\n```Alas, my dear friend, the Rings of Power are a perilous burden that should not be wielded by those of mortal race. They possess a sinister force that overcomes the spirit, enslaving their very soul. I have observed their destructive potential in Eregion long ago, where many Elven-rings were created, each infused with its own unique potency. Some more potent than others, and often, they seem to have a propensity to gravitate towards the unsuspecting. In light of our shared concern for the wellbeing of Middle Earth, I implore you to heed my words; let us not succumb to the allure of these fateful rings, lest they consume us entirely.```\r\n\r\n## Creating custom Supervised Finetuning datasets for NPCs\r\nThere are two loops integrated in the framework which allow you to create your own datasets.\r\n1. `NPC.extract_conversational_styles_from_world`: Retrieving conversations from the world and tagging the question and mood yourself\r\n2. `NPC.extract_conversational_styles_talking_to_user`: Creates conversations by talking to you\r\n\r\n### Supervised Finetuning\r\nYou can create  your own datasets with supervised finetuning,\r\naccepting or rejecting the interactions. As a result, you will come up\r\nwith a csv of interactions you can use to train or finetune your own models.\r\n\r\n```csv\r\nname||mood||question||answer\r\nGaladriel||default||Good night, Galadriel!||'Good night, my friends! '\\nsaid Galadriel. '\\nSleep in peace!\r\nGaladriel||grave||why he could say that?||....`He would be rash indeed that said that thing,' said Galadriel gravely.\r\n```\r\n\r\n## LLM integrated\r\n### Quantized\r\n- TheBloke/mistral_7b_norobots-AWQ\r\n- TheBloke/zephyr-7B-beta-AWQ\r\n- TheBloke/notus-7B-v1-AWQ\r\n- TheBloke/Starling-LM-7B-alpha-AWQ\r\n- TheBloke/Yi-6B-AWQ\r\n- TheBloke/dragon-yi-6B-v0-AWQ\r\n### Unquantized\r\n- microsoft/phi-2\r\n- stabilityai/stablelm-zephyr-3b\r\n\r\n## Embeddings for RAG\r\n- [sentence-transformers/all-MiniLM-L6-v2](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2)\r\n\r\n## CUDA and Torch in WINDOWS\r\nIf you are running on Windows on a machine with a GPU, and you get a message about not being able to find \r\nyour gpu, you need to configure CUDA for Windows.\r\n\r\n1. Go to [CUDA installation webpage](https://developer.nvidia.com/cuda-downloads).\r\n2. Select your Windows version and specifics.\r\n3. Download and install\r\n4. Uninstall torch (`pip uninstall torch`)\r\n5a. Go to requirements.txt, comment the line after LINUX for torch and uncomment the line after WINDOWS\r\n5b. Alternatively you can just run this command:\r\n```\r\npip3 install torch -i https://download.pytorch.org/whl/cu121\r\n```\r\n\r\nYou torch on windows CUDA should be working. To test it:\r\n```python\r\nimport torch\r\n\r\nif __name__ == \"__main__\":\r\n    print(torch.cuda.is_available())\r\n```\r\n\r\n\r\n## vLLM\r\n`vLLM` has been included for Fast Inference, in local, remote installations and Docker.\r\n\r\n### Local Fast inference (Paged Attention)\r\n\r\nTo use fast-inference, just run add `fast=True` to your `World` object:\r\n```python\r\nworld = World(world_name=\"Lord of the Rings\",\r\n              embeddings=EmbeddingsTypes.MINILM,\r\n              store_type=StoresTypes.CHROMA,\r\n              llm_type=LLMType.YI_6B_AWQ,\r\n              fast=True) # <---- HERE\r\n```\r\n\r\n### Remote Fast Inference\r\nTo the previous `fast` parameter, add also `remote=True`\r\n```python\r\nworld = World(world_name=\"Lord of the Rings\",\r\n              embeddings=EmbeddingsTypes.MINILM,\r\n              store_type=StoresTypes.CHROMA,\r\n              llm_type=LLMType.YI_6B_AWQ,\r\n              fast=True,   # <---- HERE\r\n              remote=True) # <---- HERE\r\n```\r\n\r\n### Streaming (only if remote!)\r\nTo the previous `fast` and `remote` parameters, add also `streaming=True`\r\n```python\r\nworld = World(world_name=\"Lord of the Rings\",\r\n              embeddings=EmbeddingsTypes.MINILM,\r\n              store_type=StoresTypes.CHROMA,\r\n              llm_type=LLMType.YI_6B_AWQ,\r\n              fast=True,   # <---- HERE\r\n              remote=True,\r\n              streaming=True) # <---- HERE\r\n```\r\n\r\n## Example data\r\n- [Lord of the Rings](https://www.kaggle.com/datasets/ashishsinhaiitr/lord-of-the-rings-text)\r\n\r\n## Notebooks\r\nYou can find notebooks in the `notebooks` folder of this project.\r\n\r\n## Demo 1: Creating a World and an NPC\r\n[Video](https://youtu.be/T-D1KVIuvjA)\r\n\r\n## Architecture\r\n<p align=\"center\">\r\n<img \r\n  width=\"50%\"\r\n  src=\"https://github.com/josejuanmartinez/mindcraft/assets/36634572/7778d4a4-6b25-4b1a-9b26-b1bfa9d94727\" alt=\"mindcraft architecture\"/>\r\n</p>\r\n\r\n## Tests\r\n`python -m pytest tests/*`\r\n\r\n## Header\r\n<p align=\"center\">\r\n<img width=\"100%\" src=\"https://github.com/josejuanmartinez/mindcraft/blob/main/galadriel.png\" alt=\"galadriel\"/>\r\n</p>\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Mindcraft: an LLM-based engine for creating real NPCs. Empowered by Hugging Face, quantized LLMs with AWQ (thanks @TheBloke) and vLLM. It follows a RAG approach with chunk or sentence splitting, and a vector store. Right now, ChromaDB is the supported Vector Store and chunk splitting using `tiktoken` or sentence splitting using `spacy` are available.",
    "version": "0.2.4",
    "project_urls": {
        "Download": "https://github.com/josejuanmartinez/mindcraft",
        "Homepage": "https://github.com/josejuanmartinez/mindcraft"
    },
    "split_keywords": [
        "nlp",
        "llm",
        "npc",
        "conversations",
        "videogames"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e1efb1ac006672c641a80086221792097e49ee18e9a6014f7504f641103d4330",
                "md5": "2d3b541e728613ba09d1d06e7dd6a540",
                "sha256": "620f83d0db5ee61ff03bfcc211d7b6cb6ca405d634a045a7817ab871b5abf8c9"
            },
            "downloads": -1,
            "filename": "mindcraft-0.2.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "2d3b541e728613ba09d1d06e7dd6a540",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10.0",
            "size": 38126,
            "upload_time": "2024-01-17T12:40:14",
            "upload_time_iso_8601": "2024-01-17T12:40:14.862129Z",
            "url": "https://files.pythonhosted.org/packages/e1/ef/b1ac006672c641a80086221792097e49ee18e9a6014f7504f641103d4330/mindcraft-0.2.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "49709a970687303ad7e1c042f9dde5b3a24be591d088403407a453489a3b6c7d",
                "md5": "a5a6a8a5270e6fe0a95bf9ba7eddd0b1",
                "sha256": "6e69b7cdfabe82390a6ec12e33d900a896c351306394ada8748ddf8c17133a7a"
            },
            "downloads": -1,
            "filename": "mindcraft-0.2.4.tar.gz",
            "has_sig": false,
            "md5_digest": "a5a6a8a5270e6fe0a95bf9ba7eddd0b1",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10.0",
            "size": 31684,
            "upload_time": "2024-01-17T12:40:17",
            "upload_time_iso_8601": "2024-01-17T12:40:17.048395Z",
            "url": "https://files.pythonhosted.org/packages/49/70/9a970687303ad7e1c042f9dde5b3a24be591d088403407a453489a3b6c7d/mindcraft-0.2.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-17 12:40:17",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "josejuanmartinez",
    "github_project": "mindcraft",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "mindcraft"
}
        
Elapsed time: 0.17769s