User Tools

Site Tools


Loki using tutorial

This is complete tutorial to usage of the Loki plugin by any DokuWiki user. It provides description of Loki features with functional examples. While reading this tutorial you will learn how to create simple Movies Knowledge Base in Loki.

First steps

Here we will show some new features you can see while working with the Loki for the first time.

New options in UI

The DokuWiki editor has its own Graphical User Interface for easier work with text. It's buttons are placed above the area of writing. Loki adds some new buttons to let you easily insert semantics into your text. All of them are listed below:

  • First is the button with “pl”. It allows you to place Prolog tag for inserting the Prolog code.
  • C inserts Category code
  • R places relation code
  • A is for attribute code
  • ? places code for ASK queries
  • S is for inserting SPARQL code and gives us 3 options:
    • S - selecting data
    • A - asking
    • D - describing

Since they are just UI buttons for inserting the code, I don't describe how to use it. It will be covered later.

Special pages

Loki has special pages for every type of semantics it uses:

  • categories page for listing all Categories
  • relations page for listing all Relations
  • attributes page for listing all Attributes

It also has groups of special pages associated with the three types mentioned before. For every attribute, relation and category used in our wiki we can create special page that describes it. After placing the attribute, relation or category in our article, we can create page like: special:category:our_category_name to describe it. After the article on the category (or relation/attribute) is created it will be listed under the special pages section in the Sitemap.

Defining categories

Let's start with simple example. In this case it will be small knowledge base of the movies and persons related to them. First we will create few pages containing only categories and titles of the movies. Then we will go further and add some details to our pages.

The movie base will be kept in the movies namespace of DokuWiki. There we will create pages about the movies. Also we will need namespace named persons for keeping pages about directors and actors. First we will create a new movie page. We will name it raiders_of_the_lost_ark and write in it some header with the full title of the movie. It will be Indiana Jones and the Raiders of the Lost Ark. Until now nothing was new for the users of the DokuWiki.

Let's provide first semantic information into this page. raiders_of_the_lost_ark is a movie so it should belong to the category named movie. Defining categories for pages is very similar to placing a link to another page. In order to place a category we write:

Raiders of the Lost Ark is a [[category:movie]]... 

We can also change the display of the category name, by placing our custom text after | character:

It is one of the [[category:movie|movies]] from the Indiana Jones series.

If you don't want to show link to the category in the text just simply put space as a custom display:

[[category:movie| ]]

In that case category tag can be placed anywhere in the page text. The most popular are at the beginning and the end of text.

In the same way we will create three additional pages with movies from the Indiana Jones series:

  • temple_of_dooom
  • last_crusade
  • kingdom_of_the_crystal_skull

All of them will have defined category movie and placed header with the full title. We will use them as a base of our example in the next points of this tutorial.

The final code of our movie page should look like this:

==== Raiders of the Lost Ark ====
[[category:movie| ]] 

Defining attributes

Attributes are used to define information included in the article. They relate to basic information that can be presented as a number, date or any other generic, non-unique data type. Attribute values itself have no meaning like: 2008 can be year as good as an amount of leaves growing on the tree. Any values that correspond to the objects that can be defined and are somehow original should be placed as relations (described later). That way we separate simple data, that would not have description from the complicated one. Also attributes should be used when we say that the object has some property like: length, weight, size and so on. In that case attributes are immanently in the subject (page). Relations are about different connections between the subject and object. They are placed outside of the subject and are another objects.

Let's continue with our movie base. Each movie has defined year of the production. It is sort of property. Then we can insert semantic notation into every movie page about the year it was produced. We will to this by placing tag:

Indiana Jones and the Raiders of the Lost Ark were produced in [[production_year:=1981]].

Of course we can place it anywhere: in the sentence like above or just separately in the table with basic information on the movie. There is no difference for Loki. The name of the attribute can be any string. Also with spaces. It is important to remember that production_year and production year attributes are different ones for Loki. If you will use space or _ symbol is up to you, but once you decide you have to be consistent.

Also here you can use | symbol to separate value from the displayed string. And also here you can hide the value by placing empty space as a custom string.

Now we will add another attributes to the movies:

  • title - full title of the movie
  • action_time - the time the action of the movie takes place
  • action_place - the places where the action takes place
  • language - primary language of the movie

In the case of the language we can define it as a relation to the language page, but for the purposes of this tutorial we will keep it like that. Same with the action place, which can be link to the countries and places. But the countries will be used as a relation in another example.

Loki does not allow for placing semantic tags inside another tags like headers. So our title of the movie will be defined below in the list of information.

Now our page raiders_of_the_lost_ark should have the code like below:

==== Raiders of the Lost Ark ====
**Title**: [[title:=Raiders of the Lost Ark]]
**Production Year**: [[production_year:=1981]]
**Action time**: [[action_time:=1936]]
**Action place**: [[action_place:=Peru]], [[action_place:=Egypt]]
**Language**: [[language:=english]]
[[category:movie| ]] 

Defining relations

While attributes are immanent information on the subject of the page, relations are representing connection of one object to another. Unlike the attributes, relations create links to target objects (pages), so we can easily jump to it. The power of the relations will be used in the queries for information later. For now it is important to give every page some relations to another pages.

In the case of our movies example we can define many relations with persons involved in production, i.e. cast, director and screenplay writers.

Adding relation is simple. For raiders_of_the_lost_ark it can be:

[[main_role::persons:harrison_ford|Harrison Ford]]

Usually the relation name should be stated as sort of connection like main_role_played_by. Since we work on a simple example, it is not that much important. But in the real works that convention should be kept.

Notice that the page used here as a value of the relation is from another namespace. It is good way of organizing our pages. In the persons namespace we can keep not only people related to the movies but also to other categories. It is important since we may have persons that work on the movies and do some other things like singing or painting. Then we don't have to create separate pages on them.

Another important note is that we can define one relation type many times. That way we will tell that the page is related in the same way with other pages. The second relation of the same name does not overwrite the value of the first. It adds another one.

The value of the relation should always be written as shown above. We can also write it as:

[[main_role::persons:Harrison Ford]]

In that way DokuWiki will create the link to the page harrison_ford, so one would say there's no difference. But in fact, there's a little trap. Semantic engine takes this value as it is: Harrison Ford. So, if we will define on another page the value as harrison_ford it will be treated as something different than Harrison Ford - even if it looks the same on the rendered page. In conclusion, we can use the second way, but by doing it we have to be consistent or we will run into problems with proper reasoning in semantic queries.

Usage of | is the same as in other cases.

In the case of movies we will add more relations:

  • Genre - from genre namespace
  • Production country - from countries namespace
  • screenplay - the author(s) of the screenplay
  • directed_by - director
  • main_character - from characters namespace
  • supporting_role - like main_role
  • supporting_character - like main_character
  • series - from namespace series

Fully created code of the page raiders_of_the_lost_ark will be:

==== Raiders of the Lost Ark ====
**Title**: [[title:=Raiders of the Lost Ark]]
**Genre**: [[genre::genres:adventure]]
**Production Year**: [[production_year:=1981]]
**Production country**: [[produced_in_country::countries:USA]]
**Screenplay**: [[screenplay::persons:Lawrence Kasdan]],                [[screenplay::persons:George Lucas]]
**Directed by**: [[directed_by::persons:steven_spielberg|Steven Spielberg]]
[[main_role::persons:harrison_ford|Harrison Ford]] - 
[[main_character::characters:indiana_jones|Indiana Jones]]
[[supporting_role::persons:karen_allen|Karen Allen]] - 	
[[supporting_character::characters:marion_ravenwood|Marion Ravenwood]]
[[supporting_role::persons:paul_freeman|Paul Freeman]] - 
[[supporting_character::characters:dr_rene_bellog|Dr René Belloq]]
**Action time**: [[action_time:=1936]]
**Action place**: [[action_place:=Peru]], [[action_place:=Egypt]]
**Series**: [[series::series:indiana_jones|Indiana Jones]]
**Language**: [[language:=english]]
[[category:movie| ]]

Our page is ready. Now we will create some other pages for actors or directors to show the power of the semantic queries. But before that we need to insert other three movies from the Indiana Jones series. Below you will find prepared text with semantic code for those pages.


==== Indiana Jones and the Temple of Doom ====
**Title**: [[title:=Indiana Jones and the Temple of Doom]]
**Genre**: [[genre::genres:adventure]]
**Production Year**: [[production_year:=1984]]
**Production country**: [[produced_in_country::countries:USA]]
**Screenplay**: [[screenplay::persons:Willard Hyuck]],[[screenplay::persons:Gloria Katz]]
**Directed by**: [[directed_by::persons:steven_spielberg|Steven Spielberg]]
[[main_role::persons:harrison_ford|Harrison Ford]] - 
[[main_character::characters:indiana_jones|Indiana Jones]]
[[supporting_role::persons:Kate Capshaw]] - 	
[[supporting_character::characters:Willie Scott]]
[[supporting_role::persons:Jonathan Ke Quan]] - 
[[supporting_character::characters:Short Round Ke Huy Quan]]
**Action time**: [[action_time:=1935]]
**Series**: [[series::series:indiana_jones|Indiana Jones]]
**Language**: [[language:=english]]
[[category:movie| ]] 


==== Indiana Jones and the Last Crusade ====
**Title**: [[title:=Indiana Jones and the Last Crusade]]
**Genre**: [[genre::genres:adventure]]
**Production Year**: [[production_year:=1989]]
**Production country**: [[produced_in_country::countries:USA]]
**Screenplay**: [[screenplay::persons:Jeffrey Boam]]
**Directed by**: [[directed_by::persons:steven_spielberg|Steven Spielberg]]
[[main_role::persons:harrison_ford|Harrison Ford]] - 
[[main_character::characters:indiana_jones|Indiana Jones]]
[[supporting_role::persons:Sean Connery]] - 	
[[supporting_character::characters:Professor Henry Jones]]
[[supporting_role::persons:Alison Doody]] - 
[[supporting_character::characters:Dr. Elsa Schneider]]
**Action time**: [[action_time:=1938]]
**Series**: [[series::series:indiana_jones|Indiana Jones]]
**Language**: [[language:=english]]
[[category:movie| ]] 


==== Indiana Jones and the Kingdom of the Crystal Skull ====
**Title**: [[title:=Indiana Jones and the Kingdom of the Crystal Skull]]
**Genre**: [[genre::genres:adventure]]
**Production year**: [[production_year:=2008]]
**Production country**: [[produced_in_country::countries:USA]]
**Screenplay**: [[screenplay::persons:David Koepp]]
**Directed by**: [[directed_by::persons:steven_spielberg|Steven Spielberg]]
[[main_role::persons:harrison_ford|Harrison Ford]] - 
[[main_character::characters:indiana_jones|Indiana Jones]]
[[supporting_role::persons:Cate Blanchett]] - 	
[[supporting_character::characters:Irina Spalko]]
[[supporting_role::persons:Karen Allen]] - 
[[supporting_character::characters:Marion Ravenwood]]
**Action time**: [[action_time:=1957]]
**Series**: [[series::series:indiana_jones|Indiana Jones]]
**Language**: [[language:=english]]
[[category:movie| ]] 

ASK semantic queries

Since now we were creating pages that were containing some semantic information. But it is only the introduction to the most powerful feature of semantic wikis - Semantic Queries. Loki uses the ASK query syntax known from the Semantic Media Wiki. It allows us to ask for pages and information they contain by using special query code.

The simplest form of ASK query has form:

{{#ask: condition }}

condition is the semantic tag that will filter information from the knowledge base. For instance we can say that we ask for all pages that has a category movie:

{{#ask: [[category:movie]] }}

By placing this on the page in wiki we will get list of pages that have defined category movie. Just like our four pages we have created before. We can use many conditions by separating them with space.

{{#ask: [[category:movie]] [[production_year:=2008]] }}

That way we will get list of movies produced in 2008. In our case there should be kingdom_of_the_crystal_skull. A condition can be category, attribute or relation. Let's create the page in the namespace persons names harrison_ford. Here we can provide some information about the actor. The example code would be:

[[category:actor| ]]
Name: [[name:=Harrison Ford]]
Full Name: [[full_name:=Harrison Ford]]
Gender: [[gender:=M]]
Birth date: [[birth_date:=1942-07-13]]
From: [[is_from::countries:USA]]

Now we can add some ask queries at the end of the page (or wherever we want to in the text). Let's say we want list of the movies with him playing main role in:

{{#ask: [[category:movie]] [[[main_role::persons:harrison_ford]] }}

That code will do the work. If we would like to include movies where he played supporting role we will use OR keyword:

{{#ask: [[category:movie]] [[[main_role::persons:harrison_ford]] [[supporting_role::persons:harrison_ford]] }}

But since we don't have such movie in the knowledge base we won't get any new movie on the list. We can also use OR with the same relation but different values and there is a shorter code possible here:

{{#ask: [[category:movie]] [[[main_role::persons:harrison_ford]] [[main_role::persons:Sean Connery]] }}

Notice that Sean Connery is placed here as it is not as sean_connery. It is because in our examples we have put him that way as a value of the relation. If we would ask for sean_connery instead we wouldn't get any result. Of course there's also no movie in our knowledge base, with Sean Connery playing main role, so let's show that problem on another example:

{{#ask: [[category:movie]] [[[main_role::persons:Harrison Ford]] }}

This will return no result, since in our knowledge base there is no information that Harrison Ford plays any main role. It is harrison_ford that does. That is why we need to be consistent in placing values while writing pages. Sean Connery value is fine, since there's no page where he is written as sean_connery. The different values were used in this example to show the problem. In the real wiki we should use style like Sean Connery or sean_connery consistently to all persons.


We can put subqueries into the conditions. It is done by inserting them between the <q></q> tags:

{{#ask: [[category:movie]] [[[main_role::<q>[[category:singer]]</q>]] }}

This example will give us list of movies, where main_role was played by a singer if we have any person with that category and there is a movie where the person is the value of the relation main_role.

We can nest subqueries by inserting another one in the <q></q> tags.

Relation chains

We can use chains of relations as a condition in our query. For example, we can ask for movies where actor who plays main role is from the USA:

{{#ask: [[category:movie]] [[main_role.is_from::countries:USA]] }}

Displaying results

By default results are shown as a table with list of pages found as a result of the query. We can add columns to the table by placing additional attributes of the ASK query. Every attribute is separated with a | symbol. Every additional column name must be written with ? symbol before. So if we want to get list of all movies with their director we will write:

{{#ask: [[category:movie]] |

We can also define the header of the column to get rid of _ symbol from the original:

{{#ask: [[category:movie]] |
?directed_by=Directed by

We can check if the result belongs to given category:

{{#ask: [[category:movie]] |
?directed_by=Directed by |

In the result the last column will have X symbol if the page has a category movie. In our case every movie will be marked.

Options for the ASK queries

We can also add options to customize the output of the query results. The options should be placed after the list of the columns described above. Options never begin with ? symbol like columns. The options are:

Option name Allowed values Description
format list of formats is available below The output format of the results - table by default
limit positive number Maximum number of displayed results
offset positive number Defines from which result page start the display. Results with smaller count won't be displayed
sort names of shown attributes Sorting columns. Can be more then one, but separated with comma
order asc, ascending, desc, descending, reverse, random Sorting order. If there are more then one sort attributes, separate it with comma. By default it is set to asc
headers show, hide Show or hide headers of the result table. By default: show
mainlabel text Label of the main column containing list of returned pages. Empty by default.
link all, subject, none Defines which elements of the result are shown as a link. By default is set to all.
default text Text shown when there are no results
intro text Text shown above the results
outro text Text shown below the results
sep text Only in list and csv formats. Defines separator for the results. By default: ,

The list of formats contains:

  • table - default one
  • broadtable - table wide for the whole page
  • list - list separated with commas (or another char defined by sep option)
  • ol - ordered list. Additional columns shown in parentheses.
  • ul - unordered list. Additional columns shown in parentheses.
  • count - count of results
  • csv - generates file on the server with results and shows the link to the file
  • debug - shows query and goal in the Prolog code, list of column, options and count of found results

Let's look at the example. It will show the table with information on the movies where Harrison Ford played the main role:

{{#ask: [[category:movie]] [[[main_role::persons:harrison_ford]] |
?title |
?production_year |

As you can see the movies are ordered chronologically by the production year.

Usage of Prolog code

Under the mask Loki uses SWI Prolog environment to provide reasoning for DokuWiki. Features of categories, attributes, relations, queries are all just shortcuts to create knowledge base in Prolog. But what is the most powerful in Loki is possibility to insert knowledge manually in Prolog language. In that way any application written in Prolog can be used explicitly on the DokuWiki page and provide additional information into knowledge base.

To place your code in Prolog you can use <pl></pl> tags. Basic usage is:

mother(X,Y) :-

In that way you can provide additional knowledge into the base of Loki. But you can do even more. pl tag takes some extra arguments:

  • file - name of the file placed in DokuWiki media directory. Knowledge placed in the file can be easily inserted into Loki knowledge on that page.
  • scope - usually used with goal. Defines the scope of searching through knowledge. Scope='pl:family' will make Prolog search in the pl:family namespace.
  • url - link to the file with Prolog code (uses curl)
  • goal - allows to provide Prolog goal. If you set this, Prolog will return to the page results of reasoning.
  • cache - allows you to define if the data from inside of the element are to be saved in the file for wiki. Then they will be available to other pages. Otherwise you can access them only in this tag (default = “true”).
  • rdf - same as format='rdf' ; see below; depreciated.
  • msgerr - defines where to show errors:
    • display - will show errors on the wiki page.
    • tofile - will save errors into the file in tmp directory.
    • ignore - default action; errors will be hidden.
  • trace - allows you to trace chosen predicates; more than one should be separated with comma
  • format - defines the format of data placed inside the tag element. Choices are:
    • prolog - default
    • rdf - RDF code;
    • sparql

If you want, you can assign that way categories, attributes and relations. You just need to use predicates:

  • wiki_category(PAGE,CATEGORY_NAME)
  • wiki_attribute(PAGE,ATTR_NAME,ATTR_VALUE)


By default Loki uses the cache for the pages. It may generate some problems. If you have page with ASK query, then its results will be loaded from cache. In that way, when you create new page that can be result of the query, it won't appear in the result.

If you want the query and all semantics on the given page to be processed then you should use NOCACHE directive:


It should be placed at the start of the chosen page.

Creating pages for semantics

There are two ways of creating special page. The first one is by clicking on the generated link in our article. But it works only for categories links. In the case of attributes and relations we need to create it's pages manually by creating pages with address:

Where is the wiki webpage domain/URL, and the attribute_name is the attribute name. In the case of relation it is pretty similar:

There's also third way of creating special pages. If we go to the special:categories page we will get the generated list of all categories used in the articles at our wiki. The unused categories won't be displayed here (but still may be already created). From that page we can easily start describing every category. With relations and attributes we can do the same.

Special pages of single attribute, category or relation are for describing the purpose of the given semantic parameter. Also once the page for one of those is created it generates the list of pages using it, which is useful for tracking the semantic data on pages.

Special pages special:categories, special:relations and special:attributes generate lists of specific semantic vocabulary used in Wiki. They have to be created manually. It is important to place

code on the page beginning to refresh lists on every page load.

docs/loki-tutorial.txt · Last modified: 2015/12/01 09:51 by kkutt