Linked Data Social Network

Ich beschäftige mich nicht nur theoretisch mit den Themen Linked Data und dezentralen sozialen Netzwerken, sondern arbeite derzeit auch ganz konkret an einer Social Network Plattform auf Basis von Linked Data. Dass was ich seit gestern online habe, würde ich aber nicht mal als Pre-Alpha bezeichnen, also erwartet nicht zu viel, falls ihr auf den gleich folgenden Link klickt.

Mein Projekt „Desone“ (Decentralized Social Network) hat derzeit auch noch wenig mit „Networking“ zu tun. Es ist eher ein Profil-Hoster und derzeit auch nur für mein eigenes Profil (Anmeldung ist noch nicht möglich, klickt so oft auf Login wie ihr wollt). Editierfunktionen bietet es auch noch nicht (nichtmal für mich selbst). Kommt aber alles noch!

Zum „Network“ wird das ganze aber dann doch wieder, weil Desone natürlich Linked Data bereitstellt. In meiner Bekanntenliste verlinke ich auf meine Kontakte bei identi.ca (StatusNet stellt praktischerweise FOAF bereit) und Twitter (semantictweet.com machts möglich) sowie auf einige wenige Personen die selbst ein FOAF-Profil hosten.

Meine Interessen verlinken zudem auf die DBpedia und mein Wohnort auf geonames.org. Wie ihr seht, sind dank Linked Data also schon sehr viele Angaben möglich, ohne das Desone selbst diese Informationen (z.B. Orte, Interessen) hosten muss. Desone hostet nur das Profil, den Rest stellt praktischerweise das Web of Data bereit.

Genug der langen Rede, schauts euch an, wenn ihr mögt: http://me.desone.org/person/aveltens#me

An die RDF-Daten kommt ihr dank Grails Content-Negotiation auf folgenden Wegen:

Ich werde euch natürlich über das Projekt auf dem Laufenden halten.

Content-Negotiation mit Grails

Content-Negotiation, zu Deutsch Inhaltsvereinbarung, ermöglicht es dem Webserver unterschiedliche Repräsentationen einer Resource an den Client auszuliefern und ist damit eine wichtige Funktion im Web of Data. Nehmen wir zum Beispiel an, die folgende URI identifiziert die Stadt Berlin:

http://example.com/city/berlin

Web-Browser fordern für gewöhnlich HTML-Dokumente an und sollen daher beim Abruf dieser URI eine schön aufbereitete Webseite mit Informationen über Berlin und ggf. ein paar Bilder ausgeliefert bekommen. Gleichzeitig sollen jedoch auch RDF-Daten über Berlin im Web of Data verfügbar gemacht werden.

In bin ein großer Freund des Grails Web-Frameworks, welches ich sowohl beruflich als auch privat nutze. Mit Grails wird – neben so ziemlich allem was Web-Entwicklung angeht – auch die Content-Negotiation zum Kinderspiel. Ich möchte das an dem bereits angesprochenen Beispiel praktisch verdeutlichen. (Ich gebe allerdings keine Einführung in Grails selbst, dazu verweise ich auf die hervorragende Dokumentation)

Nehmen wir an es gibt eine Domainklasse City, welche in verschiedenen Repräsentationen durch den CityController ausgeliefert werden soll.

Wir legen folgendes Mapping in UrlMappings.groovy an:

static mappings = {
  "/city/$name"(resource: "city")
}

Dadurch werden die Requests an URLs der Form /city/name RESTful gemappt und an den CityController weitergeleitet. D.h. GET-Requests gehen automatisch an die show-Action des Controllers POST an save u.s.w. (Details siehe Grails-Dokumentation). Außerdem wird der Part hinter /city/ als Parameter „name“ in die Action hineingegeben.

Mithilfe des withFormat-Ausdrucks kann der Controller auf verschiedene Anfrageformate unterschiedlich reagieren:

class CityController {
  def rdfRenderer

  def show = {
    def city = City.findByName(params.name)
    withFormat {
      html { return [cityInstance: city] }
      json { render city as JSON }
      rdf { rdfRenderer.render(city) }
    }
  }
}

Der rdfRenderer ist ein fiktives Beispiel. Sowas wird leider nicht von Grails mitgeliefert. RDF lässt sich aber sehr leicht mit groovyrdf generieren. Die Codeblöcke werden bei Anfragen nach den entsprechenden Formaten ausgeführt. html und json liefert Grails von Haus aus mit, was rdf bedeutet muss man jedoch kurz selbst in der Config.groovy bekannt geben:

grails.mime.types = [
  html: ['text/html','application/xhtml+xml'], // bereits vorkonfiguriert
  json: ['application/json','text/json'], // bereits vorkonfiguriert
  // [...]
  rdf: 'application/rdf+xml' // selbst ergänzt
]

Das wars im Prinzip schon, leider gibts in Grails derzeit noch einen kleinen Bug: Grails liest für die Content-Negotiation nicht wie üblich den HTTP-Accept-Header aus, sondern den Content-Type. Der Content-Type gibt eigentlich das Format der Daten an, welche man hinsendet und nicht der Daten welche man anfordert. Das lässt sich aber leicht über eine einfache Konfiguration beheben. Dazu in der Config.groovy folgende Einstellung setzen:

grails.mime.use.accept.header = true

Das wars auch schon! Abhängig vom gesetzten Accept-Header reagiert unser Controller nun anders auf den Request und kann entsprechend eine GSP rendern um eine HTML-Seite auszuliefern, JSON-Daten ausgeben oder aber RDF! Und sogar folgende URIs sind gültig:

http://example.com/city/berlin.html - Liefert immer die HTML-Seite
http://example.com/city/berlin.json - Liefert immer JSON-Daten
http://example.com/city/berlin.rdf - Liefert immer RDF-Daten

Wir haben also mit http://example.com/city/berlin eine eindeutige URI, welche die Resource Berlin identifiziert und zum anfragenden Client passende Daten ausliefert. Zudem haben wir für jede der Repräsentationen eine URI mit der entsprechenden „Dateiendung“. Das ist genau das, was wir im Web of Data brauchen 🙂

Das Web als Social Network

Linked Data eignet sich hervorragend um Soziale Netzwerke im Web abzubilden, die genauso dezentral funktionieren wir das altbekannte WWW. Wie ich bereits erklärt habe, gibt es im „Web of Data“ nicht nur Dokumente, sondern alle möglichen „Dinge“ können durch URIs identifiziert werden. Zu diesen „Dingen“ gehören auch Personen und ihre Beziehungen.

Zunächst müssen wir uns dazu noch einmal ins Gedächtnis rufen, dass Personen und die Dokumente, die sie beschreiben, zwei völlig unterschiedliche Dinge sind: You are not your Website!

Folgende URI identifiziert mich als Person: http://data.kontroversen.de/foaf.rdf#me

Man beachte das #me am Ende! Diese URI ist eine andere URI als http://data.kontroversen.de/foaf.rdf (ohne #me). Beide URIs führen im Web-Browser zwar zum gleichen RDF-Dokument, nur die letztere jedoch identifizert das RDF-Dokument, während http://data.kontroversen.de/foaf.rdf#me die Person „Angelo Veltens“ identifiziert.

Das abgerufene Dokument enthält RDF-Daten über die Resource http://data.kontroversen.de/foaf.rdf#me (mich), unter anderem meinen Namen und ein Verweis auf ein Bild von mir. Die Datei ist damit so etwas ähnliches wie ein Social-Network-Profil und legt damit den Grundstein für ein dezentrales soziales Netzwerk mit Hilfe von Linked Data.

Aber wie zur Hölle kann ich jetzt Freundschaften schließen, Status-Updates senden, Bilder sharen, Sachen liken, kommentieren, anstupsen, retweeten?! Eins nach dem anderen.

Beziehungen zwischen Personen sind sehr leicht über RDF-Tripel zum Ausdruck zu bringen. Die FOAF-Ontologie bietet zum Beispiel das Prädikat foaf:knows um zu sagen „A kennt B“. (Da FOAF sich prima für Social Networks eignet, ist auch häufig vom „FOAF-Profil“ die Rede, auch wenn natürlich weitere Ontologien im Profil verwendet werden können) Ein Beispiel aus meinem Profil:

<http://data.kontroversen.de/foaf.rdf#me>
  <foaf:knows>
    <http://fcns.eu/people/andrei/card#me>

Hinter http://fcns.eu/people/andrei/card#me verbirgt sich Andrei Sambra, was ein einfacher Abruf der URI verrät. Dank Content-Negotiation liefert ein normaler Webbrowser bei seiner URI sogar eine menschenlesbare HTML-Datei aus. Das habe ich für mein Profil leider noch nicht eingerichtet, kommt aber noch!

Jetzt mag das alles für Laien noch etwas kompliziert erscheinen, aber genausowenig wie man heute nicht mehr manuell an HTML-Dateien herumeditieren muss um ein Blog zu betreiben, wird man schon bald kein RDF mehr verstehen müssen um sein eigenes Profil im Social Web zu hosten. Es wird Anbieter geben, bei denen man mit wenigen Klicks ein Profil anlegen kann und wer mag installiert sich eine kleine Software auf seinem eigenen Webspace / Server um sein Profil zu hosten. Der Knackpunkt ist: Egal wo auch immer euer Profil liegt und wo die eurer Freunde liegen: Ihr könnt euch miteinander vernetzen. Ihr könnt euch nennen wie ihr möchtet. Ihr allein könnt bestimmen wem ihr welche Daten preisgebt. Ihr seid nicht von der Willkür einzelner Anbieter wie Google und Facebook abhängig. Das Web wird zum Social Network. Das gesamte Web mit all seinen Inhalten und Möglichkeiten!

Damit sind wir beim nächsten Punkt: Alles im Web lässt sich über Linked Data verknüpfen. Fotos, Videos, Blogartikel… Alles was im Web ist, hat auch eine URI und ich kann damit Aussagen treffen wie z.B.

<http://data.kontroversen.de/foaf.rdf#me>
  <ex:likes>
    <http://datenwissen.de/2011/09/das-web-als-social-network/>

um kenntlich zu machen, dass ich diesen Blogartikel „mag“. Ich kann Bilder hochladen wo immer ich möchte und sie mit meinem Profil verknüpfen. Ich kann Sie auf meinen eigenen Server laden. Oder bei Flickr. Das Social Web ist vollkommen dezentral. Nicht nur sind die einzelnen Profile auf viele verschiedenen Server verteilt, auch die Daten meines Profils kann ich beliebig im Web verteilen. Ein paar Bilder auf Flickr, ein paar in meinem Blog, Status-Updates bei Anbieter A, Social Bookmarks bei Anbieter B. Und das alles mit nur einem einzigen Profil, dass sich unter meiner Kontrolle befindet.

Um dies technisch zu ermöglichen muss ich mich in irgendeiner Form auf anderen Servern, bzw. bei den unterschiedlichen Anbietern mit meinem Profil „einloggen“ können. Erfreulicherweise arbeitet das W3C gerade an WebID, einem Protokoll, welches bereits heute mit allen Browsern funktioniert, da es auf SSL-Zertifikaten basiert, welche schon seit Jahrzehnten unterstützt werden. Mit WebID ist ein Login per Mausklick, ohne Username und Passwort, möglich. Ich werde das aber in einem späteren Artikel erklären, für heute soll es erst einmal reichen.

Ich hoffe es ist ungefähr klar geworden, wie ein dezentrales Social Web mit Hilfe von Linked Data möglich wird. Ansonsten zögert nicht Rückfragen zu stellen! Wer gleich ausprobieren möchte, was heute bereits möglich ist, der kann sich bei http://foaf.me/ oder http://webid.fcns.eu/ ein FOAF-Profil anlegen und sich mit mir verlinken. Egal wo ihr eurer Profil eingerichtet habt, könnt ihr dann hier etwas an die Wall posten.

Dezentrale Soziale Netzwerke – Ein grober Überblick

Ich habe mir die Tage mal ein paar Varianten von dezentralen sozialen Netzwerken angeschaut, auf die ich hier kurz eingehen möchte. Habe mich mit keinem davon tiefergehend befasst und es folgt auch keine Evaluation oder sowas. Ist vielmehr ein grober Überblick für mich selbst und wen auch immer es noch interessiert, was es im weiten Web in diese Richtung schon gibt:

Noserub

Einer der ersten mir bekannten Ansätze für dezentrale soziale Netzwerke. Gabs vor Jahren mal einen Beitrag im Elektrischen Reporter zu. Scheint aber auch leider nicht mehr aktiv voran getrieben zu werden. Letzte sichtbare Aktivitäten sind aus 2009.

One Social Web

Die Entwicklung wurde wohl erstmal eingestellt, weil man sich auf die Spezifikation konzentrieren möchte. Diese ist immerhin Stand Juli 2011. Basiert technologisch auf XMPP, vCard und Activity Streams.

Buddycloud

Macht einen vielverprechenden Eindruck, auch wenn leider noch keine Demo online ist. Dafür scheint die Entwicklung gut voran zu gehen. Setzt technologisch ebenfalls auf XMPP, aber man antwortete mir erfreulich zügig via Twitter, dass man FOAF und andere Semantic Web Standards / Technologien zumindest im Hinterkopf hat und diese in späteren Versionen zu erwarten sind. Ich bin gespannt!

The v0.1 release won’t see any semantic web technology but expect FOAF and other features to be included starting with v0.2

Lorea

So ganz klar wurde mir das Konzept auf der grausigen Website leider nicht. Gibt zwar zahlreiche Server die scheinbar ein Login via OpenID und sogar WebID unterstützen, aber leider gelang mir bei keinem ein Login auf diese Weisen. Fehlermeldung bei WebID-Login:

Couldnt login with the certificate:No Client Certificate Supplied

Fehlermeldung bei OpenID:

OpenID authentication failed: is not a valid OpenID URL.)

Diaspora

Der Vollständigkeit halber erwähne ich noch Diaspora, vermutlich das bekannsteste dezentrale Netzwerk zurzeit. Das ist auch schon recht gut voran geschritten und prinzipiell praktisch nutzbar wenn auch noch im Alpha-Status. Leider entwickelt es sich für meinen Geschmack zu sehr in Richtung „dezentrales Facebook“. Ein verteiltes Datensilo quasi, statt ein großes zentrales. Ich habe den Entwicklern vorgeschlagen FOAF und WebID zu unterstützen, habe darauf aber leider noch keine Rückmeldung.

Wer weitere Ansätze für dezentrale soziale Netzwerke kennt, möge Sie in den Kommentaren posten! Wie man mit Hilfe von Linked Data das Web zum Social Network machen kann, werde ich demnächst erläutern.