Online Tag Recommendations

This is a bonus task which will take place after tasks 1 and 2. The participants shall implement a recommendation service which can be called via HTTP by BibSonomy's recommender when a user posts a bookmark or publication. All participating recommenders are called on each posting process, one of them is choosen to actually deliver the results to the user. We can then measure the performance of the recommenders in an online setting, where timeouts are important and where we can measure which tags the user clicked.

Experimental Setup

Whenever a user enters a resource into BibSonomy (e.g. a bookmark for this challenge's website), he is presented a set of recommended tags. For that, each such post request is passed to the recommender subsystem, where according to some recommendation algorihm a suitable set of recommended tags is selected and returned to the user.

For this challenge we implemented a multiplexing recommender system where an arbitrary number of recommenders can be registered. On each post request, every recommender is queried for recommended tags, but only one is chosen (randomly) for returning tags to the user. Each recommender query and its corresponding set of recommended tags as well as the set of tags assigned to the given post by the user is logged in a database for further evaluation.

Component view

Recommenders can be either queried locally or - as for this task - remotely via http. Usability of the post process dictates low latency for the recommender subsystem, thus a timeout of 1000ms is set.

Detailed Task Description

Your task is to implement BibSonomy's TagRecommender interface realizing your own recommendation algorithm.

/**
 * This interface provides methods to get tag recommendations given posts.
 * 
 * We don't provide a method to recommend tags given a prefix of a tag, i.e., 
 * to recommend matching tags during the user types them. This must be done
 * on the client using JavaScript and the user's tag cloud. 
 */
public interface TagRecommender {

	/**
	 * Provide tag recommendations for the given post.
	 * 
	 * @param post A post describing the resource for which recommendations 
	 * should be produced. The post should contain valid intra- and inter-
	 * hashes as well as the name of the posting user.
	 * 
	 * The post might also contain already some tags (e.g., when the user 
	 * changes a post) and the recommender should/could take those into account.
	 * 
	 * @return A list of recommended tags in descending order of their relevance.
	 */
	public SortedSet<RecommendedTag> getRecommendedTags(final Post<? extends Resource> post);
	
	/** To the given list of recommended tags, the recommender shall add further tags.
	 * If it adds them at the end, at the beginning, or else, is left to the implementation.
	 * 
	 * If given an empty list, recommendedTags should contain the result of 
	 * {@link #getRecommendedTags(Post)}.
	 * 
	 * @see #getRecommendedTags(Post)
	 * @param recommendedTags A list of recommended tags (from another recommender). 
	 * @param post
	 */
        public void addRecommendedTags(final Collection<RecommendedTag> recommendedTags, 
                                       final Post<? extends Resource> post);
	
	
	/** Provide some short information about this recommender.
	 * 
	 * @return A short string describing the recommender.
	 */
	public String getInfo();
	
}

Recommended Tags are modeled by the org.bibsonomy.model.RecommendedTag class, which beside the actual tag name also considers values score and confidence for ranking recommended tags. Sets of recommended tags are thus strictly ordered lexicographically by (<score>,<confidence>,<tag name>) but two tags are treated equally, if their tag names coincide (as implemented in org.bibsonomy.model.comparators.RecommendedTagComparator). Remember that only the top five recommended tags are considered.

Your implementation can be either sent to us for integration into BibSonomy or you can run your own webservice and just tell us the corresponding url. For those who want to run their own webservice, we provided a simple servlet skelleton (src, war).

Component view

You will need:

For the remainder we assume you are building your own tag recommending webservice using tomcat version 5.5 as your servlet container and that the modules bibsonomy-common as well as bibsonomy-model are available in your java compiler's classpath. Assume your tag recommender is implemented in the class 'mypackage.MyTagRecommender' located in src/main/java/mypackage/MyTagrecommender.java:

package mypackage;

import java.util.Collection;
import java.util.SortedSet;
import java.util.TreeSet;

import org.bibsonomy.model.Post;
import org.bibsonomy.model.Resource;
import org.bibsonomy.model.RecommendedTag;
import org.bibsonomy.model.comparators.RecommendedTagComparator;
import org.bibsonomy.services.recommender.TagRecommender;

/**
 * This class implements my own super tag recommender algorithm.
 */
public class MyTagRecommender implements TagRecommender {

  public void addRecommendedTags(final Collection<RecommendedTag> recommendedTags, 
                                 final Post<? extends Resource> post) {
     recommendedTags.addAll(getRecommendedTags(post));
  }

  public String getInfo() {
     return "My super tag recommender";
  }

  /**
    * Returns recommended tags
    */
  public SortedSet<RecommendedTag> getRecommendedTags(final Post<? extends Resource> post) {

     .
     .
     .
  }
}

After building and packaging your recommender into the file 'mytagrecommender.jar', you can deploy our provided webservice wrapper, copy 'mytagrecommender.jar' together with log4j, bibsonomy-common, bibsonomy-model and bibsonomy-rest-common into tomcat's 'common/lib' directory and then add the following context parameter to tomcat's 'conf/context.xml':

   <Parameter name="TagRecommender" value="mypackage.MyTagRecommender" override="false"/>

This parameter tells our webservice wrapper which tag recommender should be queried. Now you can restart tomcat and navigate to 'http://<yourhostname>/<werbserviceContextpath>' where you find a link for testing your tag recommender.

A simple implementation of the tag recommender interface as described above is provided as source file as well as compiled jar file.

For further testing, we provided a simple client application 'ServletClient.java for querying your webservice. It is located in the webservice's source package. Using maven, you can start the client application as follows:

mvn exec:java -Dexec.mainClass=org.bibsonomy.recommender.ServletClient


Getting Feedback

We just implemented an extension of BibSonomy's tag recommender interface which allows the recommender system to collect feedback, that is: which tags a user finally assigned to a post.

For that, each posting process (which consists of entering meta data plus hitting the reload button several times) is identified by the current user's user name, it's starting date and a randomly chosen content id. These informations are available via the post object, as passed to the 'getRecommendation(...)' method.

When the final post is stored in BibSonomy's database, each recommender's 'setFeedback(...)' method is called, passing the post object to the recommender. This allows recommender systems to connect the post, as given for recommendation with the post, as finally stored in BibSonomy (using user name, date and content id for identification.

package mypackage;

import java.util.Collection;
import java.util.SortedSet;
import java.util.TreeSet;

import org.bibsonomy.model.Post;
import org.bibsonomy.model.Resource;
import org.bibsonomy.model.RecommendedTag;
import org.bibsonomy.model.comparators.RecommendedTagComparator;
import org.bibsonomy.services.recommender.TagRecommender;

/**
 * This class implements my own super tag recommender algorithm.
 */
public class MyTagRecommender implements TagRecommender {

  public void addRecommendedTags(final Collection<RecommendedTag> recommendedTags, 
                                 final Post<? extends Resource> post) {
     recommendedTags.addAll(getRecommendedTags(post));
  }

  public String getInfo() {
     return "My super tag recommender";
  }

  /**
    * Returns recommended tags
    */
  public SortedSet<RecommendedTag> getRecommendedTags(final Post<? extends Resource> post) {
     // store the post object as given for recommendation locally
     .
     .
  }

  /**
    * used for presenting the recommender the post, as it was finally stored in BibSonomy 
    */
  public void setFeedback(Post<? extends Resource> post) {
     // retrieve the post object as given for recommendation from local storage
     // and compare it to the post object as stored in the database which is given
     // as parameter object
     .
     .
   }
}

The following list summarizes, which of org.bibsonomy.model.Post's methods are used for identifying posts:

For getting your recommender's 'setFeedback(..)' method involved, you only have to use our development version of the recommender servlet (war, src) instead of the official 2.0.3 release (as described above). If you now navigate to 'http://<yourhostname>/bibsonomy-recommender-servlet' you find a link for testing your tag recommender and one for testing your feedback facilities.

Finally...

We wish you all a lot of fun and of course good luck. If you have any questions, please don't hesitate to ask us.

Happy tag recommending!