diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml
index 70d087b3..94b03356 100644
--- a/.github/workflows/sphinx.yml
+++ b/.github/workflows/sphinx.yml
@@ -1,33 +1,55 @@
-# This is a basic workflow to help you get started with Actions
+name: Build docs
-name: Build-sphinx-docs
+on:
+ push:
+ branches:
+ - main
+ - develop
+ - documentation # just for testing
+ pull_request:
-on: [push,pull_request]
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
- # This workflow contains a single job called "build"
- build:
- # The type of runner that the job will run on
+jobs:
+ docs:
runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ python-version: [ "3.10.11" ]
+ max-parallel: 5
- # Steps represent a sequence of tasks that will be executed as part of the job
steps:
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v2
-
- - name: Set up Python 3.9.18
- uses: actions/setup-python@v2
- with:
- python-version: "3.9.18"
-
- - name: Install dependencies
- run: |
- python -m pip install --upgrade pip
- # # pip install -r requirements.txt
-
- - name: Build HTML and import
- run: |
- # sphinx-apidoc -o docs dicee/ && make -C docs/ html && ghp-import -n -p -f docs/_build/html
-
-
+ - uses: actions/checkout@v3
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v4
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install -r requirements.txt
+
+ - name: Prepare required software
+ run: |
+ # epstopdf & dot & noto-fonts
+ sudo apt update && sudo apt install texlive-font-utils graphviz fonts-noto\
+
+ - name: Build docs
+ run: |
+ sphinx-build -M html docs/ docs/_build/
+
+ - name: Build LaTeX docs
+ run: |
+ sphinx-build -M latex docs/ docs/_build/
+
+ - name: Compile LaTeX document
+ uses: docker://texlive/texlive:latest
+ with:
+ args: make -C docs/_build/latex
+ - run: |
+ cp docs/_build/latex/dicee.pdf docs/_build/html/
+
+ - name: Deploy to GitHub Pages
+ uses: peaceiris/actions-gh-pages@v3
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: 'docs/_build/html'
\ No newline at end of file
diff --git a/docs/_static/documentation_options_patch.js b/docs/_static/documentation_options_patch.js
new file mode 100644
index 00000000..c43a72bb
--- /dev/null
+++ b/docs/_static/documentation_options_patch.js
@@ -0,0 +1 @@
+DOCUMENTATION_OPTIONS.LINK_SUFFIX = DOCUMENTATION_OPTIONS.FILE_SUFFIX
diff --git a/docs/_static/js/theme.js b/docs/_static/js/theme.js
new file mode 100644
index 00000000..2f013342
--- /dev/null
+++ b/docs/_static/js/theme.js
@@ -0,0 +1,243 @@
+var jQuery = (typeof(window) != 'undefined') ? window.jQuery : require('jquery');
+
+// Sphinx theme nav state
+function ThemeNav () {
+
+ var nav = {
+ navBar: null,
+ win: null,
+ winScroll: false,
+ winResize: false,
+ linkScroll: false,
+ winPosition: 0,
+ winHeight: null,
+ docHeight: null,
+ isRunning: false
+ };
+
+ nav.enable = function (withStickyNav) {
+ var self = this;
+
+ // TODO this can likely be removed once the theme javascript is broken
+ // out from the RTD assets. This just ensures old projects that are
+ // calling `enable()` get the sticky menu on by default. All other cals
+ // to `enable` should include an argument for enabling the sticky menu.
+ if (typeof(withStickyNav) == 'undefined') {
+ withStickyNav = true;
+ }
+
+ if (self.isRunning) {
+ // Only allow enabling nav logic once
+ return;
+ }
+
+ self.isRunning = true;
+ jQuery(function ($) {
+ self.init($);
+
+ self.reset();
+ self.win.on('hashchange', self.reset);
+
+ if (withStickyNav) {
+ // Set scroll monitor
+ self.win.on('scroll', function () {
+ if (!self.linkScroll) {
+ if (!self.winScroll) {
+ self.winScroll = true;
+ requestAnimationFrame(function() { self.onScroll(); });
+ }
+ }
+ });
+ }
+
+ // Set resize monitor
+ self.win.on('resize', function () {
+ if (!self.winResize) {
+ self.winResize = true;
+ requestAnimationFrame(function() { self.onResize(); });
+ }
+ });
+
+ self.onResize();
+ });
+
+ };
+
+ // TODO remove this with a split in theme and Read the Docs JS logic as
+ // well, it's only here to support 0.3.0 installs of our theme.
+ nav.enableSticky = function() {
+ this.enable(true);
+ };
+
+ nav.init = function ($) {
+ var doc = $(document),
+ self = this;
+
+ this.navBar = $('div.wy-side-scroll:first');
+ this.win = $(window);
+
+ // Set up javascript UX bits
+ $(document)
+ // Shift nav in mobile when clicking the menu.
+ .on('click', "[data-toggle='wy-nav-top']", function() {
+ $("[data-toggle='wy-nav-shift']").toggleClass("shift");
+ $("[data-toggle='rst-versions']").toggleClass("shift");
+ })
+
+ // Nav menu link click operations
+ .on('click', ".wy-menu-vertical .current ul li a", function() {
+ var target = $(this);
+ // Close menu when you click a link.
+ $("[data-toggle='wy-nav-shift']").removeClass("shift");
+ $("[data-toggle='rst-versions']").toggleClass("shift");
+ // Handle dynamic display of l3 and l4 nav lists
+ self.toggleCurrent(target);
+ self.hashChange();
+ })
+ .on('click', "[data-toggle='rst-current-version']", function() {
+ $("[data-toggle='rst-versions']").toggleClass("shift-up");
+ })
+
+ // Make tables responsive
+ $("table.docutils:not(.field-list,.footnote,.citation)")
+ .wrap("
");
+
+ // Add extra class to responsive tables that contain
+ // footnotes or citations so that we can target them for styling
+ $("table.docutils.footnote")
+ .wrap("");
+ $("table.docutils.citation")
+ .wrap("");
+
+ // Add expand links to all parents of nested ul
+ $('.wy-menu-vertical ul').not('.simple').siblings('a').each(function () {
+ var link = $(this);
+ expand = $('');
+ expand.on('click', function (ev) {
+ self.toggleCurrent(link);
+ ev.stopPropagation();
+ return false;
+ });
+ link.prepend(expand);
+ });
+ };
+
+ nav.reset = function () {
+ // Get anchor from URL and open up nested nav
+ var anchor = encodeURI(window.location.hash) || '#';
+
+ try {
+ var vmenu = $('.wy-menu-vertical');
+ var link = vmenu.find('[href="' + anchor + '"]');
+ if (link.length === 0) {
+ // this link was not found in the sidebar.
+ // Find associated id element, then its closest section
+ // in the document and try with that one.
+ var id_elt = $('.document [id="' + anchor.substring(1) + '"]');
+ var closest_section = id_elt.closest('div.section');
+ link = vmenu.find('[href="#' + closest_section.attr("id") + '"]');
+ if (link.length === 0) {
+ // still not found in the sidebar. fall back to main section
+ link = vmenu.find('[href="#"]');
+ }
+ }
+ // If we found a matching link then reset current and re-apply
+ // otherwise retain the existing match
+ if (link.length > 0) {
+ $('.wy-menu-vertical .current').removeClass('current');
+ link.addClass('current');
+ link.closest('li.toctree-l1').parent().addClass('current');
+ for (let i = 1; i <= 10; i++) {
+ link.closest('li.toctree-l' + i).addClass('current');
+ }
+ link[0].scrollIntoView();
+ }
+ }
+ catch (err) {
+ console.log("Error expanding nav for anchor", err);
+ }
+
+ };
+
+ nav.onScroll = function () {
+ this.winScroll = false;
+ var newWinPosition = this.win.scrollTop(),
+ winBottom = newWinPosition + this.winHeight,
+ navPosition = this.navBar.scrollTop(),
+ newNavPosition = navPosition + (newWinPosition - this.winPosition);
+ if (newWinPosition < 0 || winBottom > this.docHeight) {
+ return;
+ }
+ this.navBar.scrollTop(newNavPosition);
+ this.winPosition = newWinPosition;
+ };
+
+ nav.onResize = function () {
+ this.winResize = false;
+ this.winHeight = this.win.height();
+ this.docHeight = $(document).height();
+ };
+
+ nav.hashChange = function () {
+ this.linkScroll = true;
+ this.win.one('hashchange', function () {
+ this.linkScroll = false;
+ });
+ };
+
+ nav.toggleCurrent = function (elem) {
+ var parent_li = elem.closest('li');
+ parent_li.siblings('li.current').removeClass('current');
+ parent_li.siblings().find('li.current').removeClass('current');
+ var children = parent_li.find('> ul li');
+ // Don't toggle terminal elements.
+ if (children.length) {
+ children.removeClass('current');
+ parent_li.toggleClass('current');
+ }
+ }
+
+ return nav;
+};
+
+module.exports.ThemeNav = ThemeNav();
+
+if (typeof(window) != 'undefined') {
+ window.SphinxRtdTheme = {
+ Navigation: module.exports.ThemeNav,
+ // TODO remove this once static assets are split up between the theme
+ // and Read the Docs. For now, this patches 0.3.0 to be backwards
+ // compatible with a pre-0.3.0 layout.html
+ StickyNav: module.exports.ThemeNav,
+ };
+}
+
+
+// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
+// https://gist.github.com/paulirish/1579671
+// MIT license
+
+(function() {
+ var lastTime = 0;
+ var vendors = ['ms', 'moz', 'webkit', 'o'];
+ for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
+ window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
+ window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
+ || window[vendors[x]+'CancelRequestAnimationFrame'];
+ }
+
+ if (!window.requestAnimationFrame)
+ window.requestAnimationFrame = function(callback, element) {
+ var currTime = new Date().getTime();
+ var timeToCall = Math.max(0, 16 - (currTime - lastTime));
+ var id = window.setTimeout(function() { callback(currTime + timeToCall); },
+ timeToCall);
+ lastTime = currTime + timeToCall;
+ return id;
+ };
+
+ if (!window.cancelAnimationFrame)
+ window.cancelAnimationFrame = function(id) {
+ clearTimeout(id);
+ };
+}());
diff --git a/docs/_static/theme_tweak.css b/docs/_static/theme_tweak.css
new file mode 100644
index 00000000..aeedc7fa
--- /dev/null
+++ b/docs/_static/theme_tweak.css
@@ -0,0 +1,9 @@
+.rst-content dl:not(.docutils) dl dl dt {
+ width: auto;
+}
+.rst-content dl:not(.docutils) dl dt {
+ width: 96%;
+}
+.rst-content dl:not(.docutils) dt {
+ width: 100%;
+}
diff --git a/docs/_templates/search.html b/docs/_templates/search.html
new file mode 100644
index 00000000..07a4b787
--- /dev/null
+++ b/docs/_templates/search.html
@@ -0,0 +1,2 @@
+{% extends "!search.html" %}
+{% set script_files = [ '_static/documentation_options_patch.js', '_static/language_data.js' ] + script_files %}
diff --git a/docs/conf.py b/docs/conf.py
index 4201590b..1849de94 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -14,12 +14,26 @@
project = 'DICE Embeddings'
copyright = '2023, Caglar Demir'
author = 'Caglar Demir'
-release = '0.1.2'
+release = '0.1.3.2'
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
-extensions = ["sphinx.ext.todo", "sphinx.ext.viewcode", "sphinx.ext.autodoc"]
+extensions = ["autoapi.extension",
+ "sphinx.ext.githubpages",
+ "sphinx.ext.todo",
+ "sphinx.ext.viewcode",
+ "sphinx.ext.autodoc"]
+
+# autoapi for dicee.
+autoapi_dirs = ['../dicee']
+
+# by default all are included but had to reinitialize this to remove private members from showing
+autoapi_options = ['members', 'undoc-members', 'show-inheritance', 'show-module-summary', 'special-members',
+ 'imported-members']
+
+# this is set to false, so we can add it manually in index.rst together with the other .md files of the documentation.
+autoapi_add_toctree_entry = False
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
@@ -27,5 +41,25 @@
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
-html_theme = 'furo'
html_static_path = ['_static']
+
+# -- Options for LaTeX output ------------------------------------------------
+
+latex_engine = 'xelatex'
+latex_show_urls = 'footnote'
+latex_theme = 'howto'
+
+latex_elements = {
+ 'preamble': r'''
+\renewcommand{\pysiglinewithargsret}[3]{%
+ \item[{%
+ \parbox[t]{\linewidth}{\setlength{\hangindent}{12ex}%
+ \raggedright#1\sphinxcode{(}\linebreak[0]{\renewcommand{\emph}[1]{\mbox{\textit{##1}}}#2}\sphinxcode{)}\linebreak[0]\mbox{#3}}}]}
+''',
+ 'printindex': '\\def\\twocolumn[#1]{#1}\\footnotesize\\raggedright\\printindex',
+}
+
+
+def setup(app):
+ # -- Options for HTML output ---------------------------------------------
+ app.add_css_file('theme_tweak.css')
diff --git a/docs/index.rst b/docs/index.rst
index 991fc294..09b9bec0 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -3,56 +3,18 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
-Welcome to DICE Embeddings!
+Welcome to DICE Embeddings documentation!
===========================================
`DICE Embeddings `_: Hardware-agnostic Framework for Large-scale Knowledge Graph Embeddings:
=======
-
-
-.. warning::
-
- Train embedding models in multi-node, multi-GPUs, distributed data parallel or model parallel without expert knowledge!
-
-
- .. code-block:: bash
-
- // 1 CPU
- (dicee) $ dicee --dataset_dir KGs/UMLS
- // 10 CPU
- (dicee) $ dicee --dataset_dir KGs/UMLS --num_core 10
- // Distributed Data Parallel (DDP) with all GPUs
- (dicee) $ dicee --trainer PL --accelerator gpu --strategy ddp --dataset_dir KGs/UMLS
- // Model Parallel with all GPUs and low precision
- (dicee) $ dicee --trainer PL --accelerator gpu --strategy deepspeed_stage_3 --dataset_dir KGs/UMLS --precision 16
- // DDP with all GPUs on two nodes (felis and nebula):
- (dicee) cdemir@felis $ torchrun --nnodes 2 --nproc_per_node=gpu --node_rank 0 --rdzv_id 455 --rdzv_backend c10d --rdzv_endpoint=nebula -m dicee.run --trainer torchDDP --dataset_dir KGs/UMLS
- (dicee) cdemir@nebula $ torchrun --nnodes 2 --nproc_per_node=gpu --node_rank 1 --rdzv_id 455 --rdzv_backend c10d --rdzv_endpoint=nebula -m dicee.run --trainer torchDDP --dataset_dir KGs/UMLS
-
.. toctree::
:maxdepth: 2
:caption: Contents:
-Usage
--------
-
-.. code-block:: console
-
- $ git clone https://github.com/dice-group/dice-embeddings.git
-
- $ conda create -n dice python=3.9.18 --no-default-packages && conda activate dice
-
- (dice) $ pip3 install -r requirements.txt
-
-or
-
-.. code-block:: console
-
- (dice) $ pip install dicee
-
-
-
+ usage/main
+ autoapi/dicee/index
Indices and tables
-------
diff --git a/docs/usage/main.md b/docs/usage/main.md
new file mode 100644
index 00000000..de2fbefc
--- /dev/null
+++ b/docs/usage/main.md
@@ -0,0 +1,399 @@
+## Dice Embeddings!
+
+**Version:** dicee 0.1.3.2
+
+**GitHub repository:** [https://github.com/dice-group/dice-embeddings](https://github.com/dice-group/dice-embeddings)
+
+**Publisher and maintainer:** [Caglar Demir](https://github.com/Demirrr)
+
+**Contact**: [caglar.demir@upb.de](mailto:caglar.demir@upb.de)
+
+**License:** OSI Approved :: MIT License
+
+--------------------------------------------
+
+Dicee is a hardware-agnostic framework for large-scale knowledge graph embeddings.
+
+
+Knowledge graph embedding research has mainly focused on learning continuous
+representations of knowledge graphs towards the link prediction problem.
+Recently developed frameworks can be effectively applied in a wide range
+of research-related applications. Yet, using these frameworks in real-world
+applications becomes more challenging as the size of the knowledge graph
+grows
+
+We developed the DICE Embeddings framework (dicee) to compute embeddings for large-scale knowledge graphs in a hardware-agnostic manner.
+To achieve this goal, we rely on
+1. **[Pandas](https://pandas.pydata.org/) & Co.** to use parallelism at preprocessing a large knowledge graph,
+2. **[PyTorch](https://pytorch.org/) & Co.** to learn knowledge graph embeddings via multi-CPUs, GPUs, TPUs or computing cluster, and
+3. **[Huggingface](https://huggingface.co/)** to ease the deployment of pre-trained models.
+
+**Why [Pandas](https://pandas.pydata.org/) & Co. ?**
+A large knowledge graph can be read and preprocessed (e.g. removing literals) by pandas, modin, or polars in parallel.
+Through polars, a knowledge graph having more than 1 billion triples can be read in parallel fashion.
+Importantly, using these frameworks allow us to perform all necessary computations on a single CPU as well as a cluster of computers.
+
+**Why [PyTorch](https://pytorch.org/) & Co. ?**
+PyTorch is one of the most popular machine learning frameworks available at the time of writing.
+PytorchLightning facilitates scaling the training procedure of PyTorch without boilerplate.
+In our framework, we combine [PyTorch](https://pytorch.org/) & [PytorchLightning](https://www.pytorchlightning.ai/).
+Users can choose the trainer class (e.g., DDP by Pytorch) to train large knowledge graph embedding models with billions of parameters.
+PytorchLightning allows us to use state-of-the-art model parallelism techniques (e.g. Fully Sharded Training, FairScale, or DeepSpeed)
+without extra effort.
+With our framework, practitioners can directly use PytorchLightning for model parallelism to train gigantic embedding models.
+
+**Why [Hugging-face Gradio](https://huggingface.co/gradio)?**
+Deploy a pre-trained embedding model without writing a single line of code.
+
+
+## Installation
+
+### Installation from Source
+``` bash
+git clone https://github.com/dice-group/dice-embeddings.git
+conda create -n dice python=3.10.13 --no-default-packages && conda activate dice && cd dice-embeddings &&
+pip3 install -e .
+```
+or
+```bash
+pip install dicee
+```
+## Download Knowledge Graphs
+```bash
+wget https://files.dice-research.org/datasets/dice-embeddings/KGs.zip --no-check-certificate && unzip KGs.zip
+```
+To test the Installation
+```bash
+python -m pytest -p no:warnings -x # Runs >114 tests leading to > 15 mins
+python -m pytest -p no:warnings --lf # run only the last failed test
+python -m pytest -p no:warnings --ff # to run the failures first and then the rest of the tests.
+```
+
+
+
+## Knowledge Graph Embedding Models
+
+1. TransE, DistMult, ComplEx, ConEx, QMult, OMult, ConvO, ConvQ, Keci
+2. All 44 models available in https://github.com/pykeen/pykeen#models
+
+> For more, please refer to `examples`.
+
+
+## How to Train
+
+To Train a KGE model (KECI) and evaluate it on the train, validation, and test sets of the UMLS benchmark dataset.
+```python
+from dicee.executer import Execute
+from dicee.config import Namespace
+args = Namespace()
+args.model = 'Keci'
+args.scoring_technique = "KvsAll" # 1vsAll, or AllvsAll, or NegSample
+args.dataset_dir = "KGs/UMLS"
+args.path_to_store_single_run = "Keci_UMLS"
+args.num_epochs = 100
+args.embedding_dim = 32
+args.batch_size = 1024
+reports = Execute(args).start()
+print(reports["Train"]["MRR"]) # => 0.9912
+print(reports["Test"]["MRR"]) # => 0.8155
+# See the Keci_UMLS folder embeddings and all other files
+```
+where the data is in the following form
+```bash
+$ head -3 KGs/UMLS/train.txt
+acquired_abnormality location_of experimental_model_of_disease
+anatomical_abnormality manifestation_of physiologic_function
+alga isa entity
+```
+A KGE model can also be trained from the command line
+```bash
+dicee --dataset_dir "KGs/UMLS" --model Keci --eval_model "train_val_test"
+```
+dicee automaticaly detects available GPUs and trains a model with distributed data parallels technique. Under the hood, dicee uses lighning as a default trainer.
+```bash
+# Train a model by only using the GPU-0
+CUDA_VISIBLE_DEVICES=0 dicee --dataset_dir "KGs/UMLS" --model Keci --eval_model "train_val_test"
+# Train a model by only using GPU-1
+CUDA_VISIBLE_DEVICES=1 dicee --dataset_dir "KGs/UMLS" --model Keci --eval_model "train_val_test"
+NCCL_P2P_DISABLE=1 CUDA_VISIBLE_DEVICES=0,1 python dicee/scripts/run.py --trainer PL --dataset_dir "KGs/UMLS" --model Keci --eval_model "train_val_test"
+```
+Under the hood, dicee executes run.py script and uses lighning as a default trainer
+```bash
+# Two equivalent executions
+# (1)
+dicee --dataset_dir "KGs/UMLS" --model Keci --eval_model "train_val_test"
+# Evaluate Keci on Train set: Evaluate Keci on Train set
+# {'H@1': 0.9518788343558282, 'H@3': 0.9988496932515337, 'H@10': 1.0, 'MRR': 0.9753123402351737}
+# Evaluate Keci on Validation set: Evaluate Keci on Validation set
+# {'H@1': 0.6932515337423313, 'H@3': 0.9041411042944786, 'H@10': 0.9754601226993865, 'MRR': 0.8072362996241839}
+# Evaluate Keci on Test set: Evaluate Keci on Test set
+# {'H@1': 0.6951588502269289, 'H@3': 0.9039334341906202, 'H@10': 0.9750378214826021, 'MRR': 0.8064032293278861}
+
+# (2)
+CUDA_VISIBLE_DEVICES=0,1 python dicee/scripts/run.py --trainer PL --dataset_dir "KGs/UMLS" --model Keci --eval_model "train_val_test"
+# Evaluate Keci on Train set: Evaluate Keci on Train set
+# {'H@1': 0.9518788343558282, 'H@3': 0.9988496932515337, 'H@10': 1.0, 'MRR': 0.9753123402351737}
+# Evaluate Keci on Train set: Evaluate Keci on Train set
+# Evaluate Keci on Validation set: Evaluate Keci on Validation set
+# {'H@1': 0.6932515337423313, 'H@3': 0.9041411042944786, 'H@10': 0.9754601226993865, 'MRR': 0.8072362996241839}
+# Evaluate Keci on Test set: Evaluate Keci on Test set
+# {'H@1': 0.6951588502269289, 'H@3': 0.9039334341906202, 'H@10': 0.9750378214826021, 'MRR': 0.8064032293278861}
+```
+Similarly, models can be easily trained with torchrun
+```bash
+torchrun --standalone --nnodes=1 --nproc_per_node=gpu dicee/scripts/run.py --trainer torchDDP --dataset_dir "KGs/UMLS" --model Keci --eval_model "train_val_test"
+# Evaluate Keci on Train set: Evaluate Keci on Train set: Evaluate Keci on Train set
+# {'H@1': 0.9518788343558282, 'H@3': 0.9988496932515337, 'H@10': 1.0, 'MRR': 0.9753123402351737}
+# Evaluate Keci on Validation set: Evaluate Keci on Validation set
+# {'H@1': 0.6932515337423313, 'H@3': 0.9041411042944786, 'H@10': 0.9754601226993865, 'MRR': 0.8072499937521418}
+# Evaluate Keci on Test set: Evaluate Keci on Test set
+{'H@1': 0.6951588502269289, 'H@3': 0.9039334341906202, 'H@10': 0.9750378214826021, 'MRR': 0.8064032293278861}
+```
+You can also train a model in multi-node multi-gpu setting.
+```bash
+torchrun --nnodes 2 --nproc_per_node=gpu --node_rank 0 --rdzv_id 455 --rdzv_backend c10d --rdzv_endpoint=nebula dicee/scripts/run.py --trainer torchDDP --dataset_dir KGs/UMLS
+torchrun --nnodes 2 --nproc_per_node=gpu --node_rank 1 --rdzv_id 455 --rdzv_backend c10d --rdzv_endpoint=nebula dicee/scripts/run.py --trainer torchDDP --dataset_dir KGs/UMLS
+```
+Train a KGE model by providing the path of a single file and store all parameters under newly created directory
+called `KeciFamilyRun`.
+```bash
+dicee --path_single_kg "KGs/Family/family-benchmark_rich_background.owl" --model Keci --path_to_store_single_run KeciFamilyRun --backend rdflib
+```
+where the data is in the following form
+```bash
+$ head -3 KGs/Family/train.txt
+_:1 .
+ .
+ .
+```
+**Apart from n-triples or standard link prediction dataset formats, we support ["owl", "nt", "turtle", "rdf/xml", "n3"]***.
+Moreover, a KGE model can be also trained by providing **an endpoint of a triple store**.
+```bash
+dicee --sparql_endpoint "http://localhost:3030/mutagenesis/" --model Keci
+```
+For more, please refer to `examples`.
+
+
+## Creating an Embedding Vector Database
+
+##### Learning Embeddings
+```bash
+# Train an embedding model
+dicee --dataset_dir KGs/Countries-S1 --path_to_store_single_run CountryEmbeddings --model Keci --p 0 --q 1 --embedding_dim 32 --adaptive_swa
+```
+#### Loading Embeddings into Qdrant Vector Database
+```bash
+# Ensure that Qdrant available
+# docker pull qdrant/qdrant && docker run -p 6333:6333 -p 6334:6334 -v $(pwd)/qdrant_storage:/qdrant/storage:z qdrant/qdrant
+diceeindex --path_model "CountryEmbeddings" --collection_name "dummy" --location "localhost"
+```
+#### Launching Webservice
+```bash
+diceeserve --path_model "CountryEmbeddings" --collection_name "dummy" --collection_location "localhost"
+```
+##### Retrieve and Search
+
+Get embedding of germany
+```bash
+curl -X 'GET' 'http://0.0.0.0:8000/api/get?q=germany' -H 'accept: application/json'
+```
+
+Get most similar things to europe
+```bash
+curl -X 'GET' 'http://0.0.0.0:8000/api/search?q=europe' -H 'accept: application/json'
+{"result":[{"hit":"europe","score":1.0},
+{"hit":"northern_europe","score":0.67126536},
+{"hit":"western_europe","score":0.6010134},
+{"hit":"puerto_rico","score":0.5051694},
+{"hit":"southern_europe","score":0.4829831}]}
+```
+
+
+
+
+## Answering Complex Queries
+
+```python
+# pip install dicee
+# wget https://files.dice-research.org/datasets/dice-embeddings/KGs.zip --no-check-certificate & unzip KGs.zip
+from dicee.executer import Execute
+from dicee.config import Namespace
+from dicee.knowledge_graph_embeddings import KGE
+# (1) Train a KGE model
+args = Namespace()
+args.model = 'Keci'
+args.p=0
+args.q=1
+args.optim = 'Adam'
+args.scoring_technique = "AllvsAll"
+args.path_single_kg = "KGs/Family/family-benchmark_rich_background.owl"
+args.backend = "rdflib"
+args.num_epochs = 200
+args.batch_size = 1024
+args.lr = 0.1
+args.embedding_dim = 512
+result = Execute(args).start()
+# (2) Load the pre-trained model
+pre_trained_kge = KGE(path=result['path_experiment_folder'])
+# (3) Single-hop query answering
+# Query: ?E : \exist E.hasSibling(E, F9M167)
+# Question: Who are the siblings of F9M167?
+# Answer: [F9M157, F9F141], as (F9M167, hasSibling, F9M157) and (F9M167, hasSibling, F9F141)
+predictions = pre_trained_kge.answer_multi_hop_query(query_type="1p",
+ query=('http://www.benchmark.org/family#F9M167',
+ ('http://www.benchmark.org/family#hasSibling',)),
+ tnorm="min", k=3)
+top_entities = [topk_entity for topk_entity, query_score in predictions]
+assert "http://www.benchmark.org/family#F9F141" in top_entities
+assert "http://www.benchmark.org/family#F9M157" in top_entities
+# (2) Two-hop query answering
+# Query: ?D : \exist E.Married(D, E) \land hasSibling(E, F9M167)
+# Question: To whom a sibling of F9M167 is married to?
+# Answer: [F9F158, F9M142] as (F9M157 #married F9F158) and (F9F141 #married F9M142)
+predictions = pre_trained_kge.answer_multi_hop_query(query_type="2p",
+ query=("http://www.benchmark.org/family#F9M167",
+ ("http://www.benchmark.org/family#hasSibling",
+ "http://www.benchmark.org/family#married")),
+ tnorm="min", k=3)
+top_entities = [topk_entity for topk_entity, query_score in predictions]
+assert "http://www.benchmark.org/family#F9M142" in top_entities
+assert "http://www.benchmark.org/family#F9F158" in top_entities
+# (3) Three-hop query answering
+# Query: ?T : \exist D.type(D,T) \land Married(D,E) \land hasSibling(E, F9M167)
+# Question: What are the type of people who are married to a sibling of F9M167?
+# (3) Answer: [Person, Male, Father] since F9M157 is [Brother Father Grandfather Male] and F9M142 is [Male Grandfather Father]
+
+predictions = pre_trained_kge.answer_multi_hop_query(query_type="3p", query=("http://www.benchmark.org/family#F9M167",
+ ("http://www.benchmark.org/family#hasSibling",
+ "http://www.benchmark.org/family#married",
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")),
+ tnorm="min", k=5)
+top_entities = [topk_entity for topk_entity, query_score in predictions]
+print(top_entities)
+assert "http://www.benchmark.org/family#Person" in top_entities
+assert "http://www.benchmark.org/family#Father" in top_entities
+assert "http://www.benchmark.org/family#Male" in top_entities
+```
+For more, please refer to `examples/multi_hop_query_answering`.
+
+
+## Predicting Missing Links
+
+```python
+from dicee import KGE
+# (1) Train a knowledge graph embedding model..
+# (2) Load a pretrained model
+pre_trained_kge = KGE(path='..')
+# (3) Predict missing links through head entity rankings
+pre_trained_kge.predict_topk(h=[".."],r=[".."],topk=10)
+# (4) Predict missing links through relation rankings
+pre_trained_kge.predict_topk(h=[".."],t=[".."],topk=10)
+# (5) Predict missing links through tail entity rankings
+pre_trained_kge.predict_topk(r=[".."],t=[".."],topk=10)
+```
+
+
+
+## Downloading Pretrained Models
+
+```python
+from dicee import KGE
+# (1) Load a pretrained ConEx on DBpedia
+model = KGE(url="https://files.dice-research.org/projects/DiceEmbeddings/KINSHIP-Keci-dim128-epoch256-KvsAll")
+```
+
+- For more please look at [dice-research.org/projects/DiceEmbeddings/](https://files.dice-research.org/projects/DiceEmbeddings/)
+
+
+
+## How to Deploy
+
+```python
+from dicee import KGE
+KGE(path='...').deploy(share=True,top_k=10)
+```
+
+
+
+## Docker
+To build the Docker image:
+```
+docker build -t dice-embeddings .
+```
+
+To test the Docker image:
+```
+docker run --rm -v ~/.local/share/dicee/KGs:/dicee/KGs dice-embeddings ./main.py --model AConEx --embedding_dim 16
+```
+
+
+## How to cite
+Currently, we are working on our manuscript describing our framework.
+If you really like our work and want to cite it now, feel free to chose one :)
+```
+# Keci
+@inproceedings{demir2023clifford,
+ title={Clifford Embeddings--A Generalized Approach for Embedding in Normed Algebras},
+ author={Demir, Caglar and Ngonga Ngomo, Axel-Cyrille},
+ booktitle={Joint European Conference on Machine Learning and Knowledge Discovery in Databases},
+ pages={567--582},
+ year={2023},
+ organization={Springer}
+}
+# LitCQD
+@inproceedings{demir2023litcqd,
+ title={LitCQD: Multi-Hop Reasoning in Incomplete Knowledge Graphs with Numeric Literals},
+ author={Demir, Caglar and Wiebesiek, Michel and Lu, Renzhong and Ngonga Ngomo, Axel-Cyrille and Heindorf, Stefan},
+ booktitle={Joint European Conference on Machine Learning and Knowledge Discovery in Databases},
+ pages={617--633},
+ year={2023},
+ organization={Springer}
+}
+# DICE Embedding Framework
+@article{demir2022hardware,
+ title={Hardware-agnostic computation for large-scale knowledge graph embeddings},
+ author={Demir, Caglar and Ngomo, Axel-Cyrille Ngonga},
+ journal={Software Impacts},
+ year={2022},
+ publisher={Elsevier}
+}
+# KronE
+@inproceedings{demir2022kronecker,
+ title={Kronecker decomposition for knowledge graph embeddings},
+ author={Demir, Caglar and Lienen, Julian and Ngonga Ngomo, Axel-Cyrille},
+ booktitle={Proceedings of the 33rd ACM Conference on Hypertext and Social Media},
+ pages={1--10},
+ year={2022}
+}
+# QMult, OMult, ConvQ, ConvO
+@InProceedings{pmlr-v157-demir21a,
+ title = {Convolutional Hypercomplex Embeddings for Link Prediction},
+ author = {Demir, Caglar and Moussallem, Diego and Heindorf, Stefan and Ngonga Ngomo, Axel-Cyrille},
+ booktitle = {Proceedings of The 13th Asian Conference on Machine Learning},
+ pages = {656--671},
+ year = {2021},
+ editor = {Balasubramanian, Vineeth N. and Tsang, Ivor},
+ volume = {157},
+ series = {Proceedings of Machine Learning Research},
+ month = {17--19 Nov},
+ publisher = {PMLR},
+ pdf = {https://proceedings.mlr.press/v157/demir21a/demir21a.pdf},
+ url = {https://proceedings.mlr.press/v157/demir21a.html},
+}
+# ConEx
+@inproceedings{demir2021convolutional,
+title={Convolutional Complex Knowledge Graph Embeddings},
+author={Caglar Demir and Axel-Cyrille Ngonga Ngomo},
+booktitle={Eighteenth Extended Semantic Web Conference - Research Track},
+year={2021},
+url={https://openreview.net/forum?id=6T45-4TFqaX}}
+# Shallom
+@inproceedings{demir2021shallow,
+ title={A shallow neural model for relation prediction},
+ author={Demir, Caglar and Moussallem, Diego and Ngomo, Axel-Cyrille Ngonga},
+ booktitle={2021 IEEE 15th International Conference on Semantic Computing (ICSC)},
+ pages={179--182},
+ year={2021},
+ organization={IEEE}
+```
+For any questions or wishes, please contact: ```caglar.demir@upb.de```
diff --git a/docs/using_dice_embedding_framework/Training.md b/docs/usage/training.md
similarity index 100%
rename from docs/using_dice_embedding_framework/Training.md
rename to docs/usage/training.md
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 00000000..0ca198b2
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,17 @@
+torch>=2.2.0
+lightning>=2.1.3
+pandas>=2.1.0
+polars>=0.16.14
+scikit-learn>=1.2.2
+pyarrow>=11.0.0
+pykeen>=1.10.2
+zstandard>=0.21.0
+pytest>=7.2.2
+psutil>=5.9.4
+ruff>=0.0.284
+gradio>=3.23.0
+rdflib>=7.0.0
+tiktoken>=0.5.1
+matplotlib>=3.8.2
+sphinx-autoapi>=3.0.0
+sphinx>=7.2.6
\ No newline at end of file