home.social

#digitalemundigkeit — Public Fediverse posts

Live and recent posts from across the Fediverse tagged #digitalemundigkeit, aggregated by home.social.

fetched live
  1. Der Berliner #FediDay geht in die dritte Runde: Vom 11. bis 13. September treffen sich in der c-base Menschen, die das Fediverse weiterdenken, weiterentwickeln und gemeinsam gestalten wollen. Mehr als 70 Vorträge, Workshops und Diskussionen machen ihn zur größten Konferenz für alternative soziale Netzwerke.

    Mit dabei ist unsere Kollegin Leena Simon (@reticuleena) gleich dreimal:

    * Sa., 12. September, 17.30 Uhr: „Killer-Feature heißt Mitbestimmung“
    * Sa., 12. September, 18.30 Uhr: Workshop „Das Killer-Feature heißt Mitbestimmung“
    * So., 13. September, 12.30 Uhr: „Die Reichweitenlüge: Adam Scheinriese und seine Zahlen“

    Außerdem diskutiert sie anschließend ab 13.30 Uhr bei „Reichweite my Ass!!!“ über Kreation und Kuratierung im Fediverse.

    Programm, Ort und Tickets:
    berlinfedi.day/

    #Fediverse #Mastodon #Berlin #DigitaleMündigkeit #Fediday

  2. @virgil_tibbs @ralphruthe Jetzt wäre die Unterhaltung beinahe in die falsche Richtung gelaufen.
    Es geht nicht darum einem US-Konzern zu schaden oder zu nützen. Es geht darum die Datenwüste, die US- Tec-Konzerne aus dem Internet gemacht haben, wieder zu beleben.
    Hier ein guter Beitrag wie unser Internet in Wirklichkeit hinter der 'Matrix' aussieht: "Big Tech muss weg! - WebMontag Spezial aus Kiel mit Dr. Martin Andree"
    tube.tchncs.de/w/3vjXp2fQzBXjg
    #digitaleMündigkeit #digitaleunabhangigkeit

  3. Technodiversität als Nordstern für digitale Mündigkeit

    In der gegenwärtigen KI-Debatte diskutieren wir meinem Eindruck nach viel über die Frage, wie wir KI als Werkzeug und auch als Impuls für eine veränderte Lernkultur nutzen können. Außerdem reflektieren wir – meist unter der Überschrift der ethischen Dimension von KI – über gesamtgesellschaftliche Implikationen wie Ressourcenverbrauch, Bias oder soziale und demokratische Konsequenzen. Was dabei aus meiner Sicht häufig aus dem Blick gerät, ist die Frage nach einer alternativen Gestaltung unserer digitalen Technologien und damit eben auch von KI. In diesem Sinne ließe sich bei der ethischen Dimension von KI nicht nur fragen: „Was macht KI-Technologie mit unserer Gesellschaft?“, sondern auch: „Wie könnte KI-Technologie bzw. unsere Digitalität insgesamt anders gestaltet sein, sodass sie ein gutes Leben für alle unterstützt?“ Diese Frage ist sehr viel grundsätzlicher und sie wird angesichts der immensen Prägung unserer Gesellschaft durch digitale Technologien immer relevanter.

    Hilfreich finde ich hier die Überlegungen des Technikphilosophen Yuk Hui, die ich als Denkanstoß (und Gedächtnisstütze für mich) hier aufschreiben und teilen will. Ich finde sie eine gute theoretische Grundlage, um Gestaltbarkeit von Technologie in den Blick zu nehmen und dazu insbesondere Dezentralität als Möglichkeit für föderierte und damit unterschiedliche, aber zugleich vernetzte digitale Systeme – wie sie etwa in offenen Projekten wie dem Fediverse verankert ist – nicht nur als technisches Funktionsprinzip, sondern als gesamtgesellschaftliches Erfordernis in der Digitalität zu begründen.

    Ausgangspunkt von Yuk Hui ist, dass sich digitale Technologien seiner Beobachtung nach zunehmend vom ‚organisierten Anorganischen‘ hin zum ‚organisierenden Anorganischen‘ verändern. Es findet somit eine Verschiebung statt von Maschinen als Gegenständen menschlicher Organisation hin zu technischen Systemen, die selbst Prozesse strukturieren, steuern und Rückkopplungen erzeugen. Damit wird Technologie immer prägender für unsere Gesellschaft und umso wichtiger wird es, die Gestaltung bewusst anzugehen. Ein weiterer Begriff von ihm ist in diesem Sinne ‚Kosmotechnik‘. Er meint damit, dass Technologie nicht neutral ist, sondern immer in einem bestimmten Kontext entwickelt wird und die damit verbundenen Orientierungen in sich trägt und nicht-dualistisch gedacht ist. Technologie ist somit eigentlich nicht feststehend und universell.

    Sein Gegenentwurf angesichts der Vielfältigkeit unserer Welt vor dem Hintergrund einer angenommen Kosmotechnik ist Technodiversität – also eine Art der technologischen Gestaltung, die immer von einer spezifischen Situation ausgeht und somit angesichts der Vielfalt unserer Welt nicht normiert und zentralisiert wäre.

    Die gegenwärtige Entwicklung geht mit zunehmender Monopolisierung dagegen in die entgegensetzte Richtung von Technodiversität: Hier gibt es nur noch eine oder wenige Technologie zur Auswahl, die dann als besonders überlegen und effizient eingeordnet wird, deshalb gewählt wird und dann durch die Sammlung und Auswertung von Nutzer:innen-Daten immer besser optimiert werden kann. Es entstehen Lock-In Effekte. Dieser Prozess wird noch dadurch verstärkt, dass die Technologie im Interesse ihrer Vermarktung meist so entwickelt wird, dass sie sehr intuitiv funktioniert. Das ist einerseits hilfreich, weil es Hürden abbaut. Zugleich wird Technologie damit etwas, was uns zur Verfügung gestellt wird, was intransparent bleibt und nicht das, was wir entwickeln. Die Herausforderung, Technologie zu gestalten und sie überhaupt als gestaltbar zu erkennen, tritt dabei immer mehr in den Hintergrund.

    Diese Art der Technologie-Entwicklung funktioniert zugleich immer schneller, so dass Maschinen einem noch stärker als tendenziell unbeherrschbar und gegeben erscheinen. Technodiversität würde dagegen wie beschrieben bedeuten, aus einer konkreten Konstellation heraus zu gestalten.

    Vor diesem Hintergrund erscheint mir Technodiversität – auch wenn es erstmal vielleicht wenig spektakulär klingt – in der Darstellung von Yuk Hui als hilfreicher Nordstern für digitale Mündigkeit im Kontext von Bildung. Die inhaltliche Auseinandersetzung damit kann Hand in Hand gehen mit praktischen Erkundungen – zum Beispiel zu dezentralen und föderierten Systemen. Ein sehr hilfreicher und konkreter Einstieg kann hier das Fediverse als ein von unten gestalteter Lern- und Austauschraum oder auch das Kennenlernen und Mitgestalten von Open-Source-Projekten sein. Hier haben wir es zwar weiterhin vielfach mit Standards zu tun, die aber offen sind und so nur einen übergreifenden Rahmen vorgeben, um dann insbesondere Föderierung zu ermöglichen. Innerhalb dieses Rahmens ist sehr viel Gestaltung möglich, was zu Vielfalt führt und somit Technodiversität auch auf einer größeren Ebene überhaupt denkbar und dann auch erlernbar macht. Die bei solch einer erkundenden und ausprobierenden Variante von Technologie fast zwangsläufig auftretenden Hindernisse und Irritationen wären dann als Gegenentwurf zu einer zunehmend intuitiv-nutzbaren und zugleich intransparenten Technologie kein beklagenswertes Problem, sondern ein wünschenswerter Lernanlass.

    #DigitaleMündigkeit
  4. Save Social sucht Verstärkung!

    Du willst dazu beitragen, dass soziale Netzwerke wieder den Menschen dienen statt den Plattformkonzernen? Dann könnte das genau die richtige Stelle für dich sein.

    Save Social sucht Unterstützung im Bereich Kommunikation. Wenn du Lust auf Öffentlichkeitsarbeit, Kampagnen, Social Media und digitale Zivilgesellschaft hast, schau dir die Ausschreibung an und bewirb dich:

    savesocial.eu/wp-content/uploa

    Bitte weitersagen – gute Leute für gute Projekte werden immer gebraucht.

    #SaveSocial #Job #Stellenangebot #Kommunikation #NGO #Zivilgesellschaft #Fediverse #DigitaleMündigkeit

  5. Sensation: ALDI zeigt, dass es auch anders geht.

    ALDI schafft die App-exklusiven Rabatte ab. Preisnachlässe gibt es künftig wieder ohne Smartphone, ohne Konto und ohne Datenspur. Das ist ein wichtiger Schritt gegen #Digitalzwang und gegen Preisdiskriminierung durch personalisierte Apps.

    Genau dafür kämpfen wir seit Jahren: vom BigBrotherAward für Payback über unsere Kritik an Rabatt-Apps bis zur Petition für ein Recht auf ein Leben ohne Digitalzwang. Wir freuen uns über diesen Erfolg und hoffen, dass andere Unternehmen diesem Beispiel folgen.

    Mehr dazu: digitalcourage.de/blog/2026/al

    #Digitalzwang #DigitaleMündigkeit #Datenschutz #Verbraucherschutz #Grundrechte #BigBrotherAwards #Aldi

  6. @goodthinkhunting Sorry, da fehlt mir die Phantasie, ein kleines Sahneröschen als schmackhaft auf einem vergammelten Kuchen zu genießen.

    Wir hätten in #Schule und #Sportverein die Chance bewusst auf #Whatsapp zu verzichten. Vollkommen zu Recht und das wäre super easy. Habe das in Schule und Verein erfolgreich umgesetzt.

    Es fehlt aber Wille und Kompetenz bei Verbänden und Kultusministerien.

    #digitaleMündigkeit

  7. Gut, dass es AIS.chat gibt!

    Bei aktuellen KI-Veranstaltungen im Bildungskontext kommt früher oder später die Rede auf AIS.chat, also die Chatbot-Oberfläche, die vom FWU Institut für Film und Bild in Wissenschaft und Unterricht im Auftrag der 16 Bundesländer und gefördert vom Bundesbildungsministerium angeboten wird und inzwischen in immer mehr Bundesländern an Schulen zur Verfügung steht. Die Äußerungen, die ich zu AIS.chat wahrnehme, sind dann meist negativ: Das Angebot sei viel zu langsam und schwerfällig, der notwendig gewordene Namenswechsel peinlich und lächerlich (früher hieß das Produkt ‚telli‘ und musste umbenannt werden, weil die Erlaubnis zur Nutzung der Marke auslief) und überhaupt würde es zig, ebenfalls kostenfreie KI-Tools geben, die Schüler*innen längst selbstverständlich nutzen und die auch für Lehrkräfte viel attraktiver seien.

    Ich kann diese Kritik erst einmal gut nachvollziehen: Es ist super nervig, wenn Technologie nicht so funktioniert, wie man sie sich wünscht oder braucht. Und gerade wenn im Kontext von KI eigentlich Entlastung erhofft wird, dann ist ein Tool, das vermeintlich viel weniger kann und weniger Leistung bringt als andere Angebote, natürlich ein Ärgernis. Zumal in einem stressigen und oft überfordernden Schulalltag. Und trotzdem finde ich: Es ist gut und sinnvoll, dass es AIS.chat gibt. Das möchte ich im Folgenden kurz begründen:

    Sehr gut passend ist für mich für diese Begründung ein Vergleich mit der Deutschen Bahn. Als Viel-Bahnfahrerin bin ich super genervt davon, dass Züge ausfallen, Verspätungen eher Normalität als Ausnahme sind und die Preispolitik der Bahn aus meiner Sicht oft in eine verkehrte Richtung geht. Trotzdem bin ich sehr froh darüber, dass es die Deutsche Bahn gibt – und meine Alternative wäre ganz sicher nicht, eine (noch stärkere) Privatisierung oder gar ihre Abschaffung zu fordern. Ganz im Gegenteil: Ich setze mich dafür ein und werbe dafür, dass die Bahn als Teil öffentlicher Infrastruktur für alle in guter Qualität zur Verfügung steht. Ich tue das wohl wissend, dass angesichts von Sanierungsstau und aktuellen politischen Mehrheitsverhältnissen wahrscheinlich keine direkte Besserung in Sicht ist. (Bis dahin kann ich Bahnfahren im Rahmen meiner Möglichkeiten angenehmer und freudvoller machen, z.B. durch direkte Rücksichtnahme, Hilfsbereitschaft und Akzeptanz der Situation, was dann tatsächlich sehr oft zu unverhofften und spannenden Bekanntschaften und Erlebnissen führt.)

    Genau solch eine Haltung wünsche ich mir von uns allen, als im Bildungskontext tätigen Menschen, auch in Bezug auf AIS.chat. Und, anders als bei der Deutschen Bahn, befindet sich das Tool im Aufbau, es wird kontinuierlich besser und wir haben deutlich mehr Gestaltungs- und Entwicklungsoptionen. Lasst sie uns nutzen!

    Ja, es mag sein, dass die Leistung des Angebots manches Mal noch zu wünschen übrig lässt. Es mag auch sein, dass das Angebot zu spät kam und eigentlich schon viel früher hätte vorbereitet werden müssen. Und es ist verständlich, dass die Entwicklungen daran oft schwerfällig und mühsam erscheinen. Genau das liegt aber zu einem großen Teil in der Natur der Sache, wenn wir demokratisch, mit vielen unterschiedlichen Beteiligten und sicherlich in der Tat auch mit oft noch fehlender digitaler Expertise in manchen Behörden und Ministerien genau wie auch an vielen Schulen an einem digitalen Angebot zu KI arbeiten.

    Der Wert dieser Möglichkeit bemisst sich darum aber auch nicht allein in einer wie auch immer definierten ‚Effizienz‘, sondern allen voran auch in dem dadurch ermöglichten Lernprozess. Als Pädagog*innen sind wir dazu prädestiniert, genau diesen Lernprozess in der Debatte stark zu machen und auch ganz konkret mitzugestalten.

    Damit das nicht missverständlich ist: Etwaige technische Schwächen gehören sicherlich behoben. Was hingegen kein Mangel ist, sondern Ausdruck einer bewussten Entscheidung, sind die demokratischen Abstimmungs- und Entwicklungsprozesse, die für ein gemeinsames Aushandeln (und damit auch Lernen) immer Zeit benötigen. In diesem Sinne gilt tatsächlich: It’s not a bug, it’s a feature!

    Noch wichtiger finde ich: Neben dem ermöglichten Lernen zu Technologie eröffnet AIS.chat, weil es in erster Linie ‚unser‘ Tool ist, die Perspektive einer gemeinwohlorientierten Technologie als digitale Infrastruktur für den Bildungsbereich. Das ist der für mich größte Unterschied zu anderen Anbietern und Angeboten.

    Ich finde es in dieser Situation zugleich verständlich, dass in Lernprozessen immer wieder auch auf andere KI-Tools zurückgegriffen wird – sowohl weil man selbst vielleicht erkunden will, was anderes möglich ist, als auch weil man die Lebenswelt von Lernenden berücksichtigen will und deshalb natürlich Räume schaffen sollte, um gemeinsam zu reflektieren, was denn ansonsten genutzt wird und wie die Erfahrungen damit sind. Das ist dann aber kein Widerspruch dazu, das Angebot von AIS.chat zu unterstützen, anstatt es grundsätzlich infrage zu stellen. AIS.chat muss nicht alles ersetzen, was andere Tools bieten. Je mehr Menschen sich allerdings in den weiteren Entwicklungsprozess einbringen, mitdenken und im Rahmen der jeweils eigenen Möglichkeiten Prozesse koordinieren und Abstimmungen gestalten, umso besser wird sich das Angebot für uns alle weiter entwickeln. Und je stärker werden dann irgendwann viele, weitere Tools vielleicht überflüssig(er).

    Solch ein Einbringen und Mitdenken kann natürlich auch Kritik beinhalten. Auch daraus kann ja Entwicklung angestoßen werden. Ich habe z.B. selbst schon sehr früh meinen Unmut darüber aufgeschrieben, dass AIS.chat aus meiner Sicht nur wenig transformativ und damit nicht bewusst als pädagogisch-ermöglichende Alternative zu anderen Anbietern bei der KI-Nutzung gestaltet wird. Einiges davon wurde und wird aufgegriffen, es werden im FWU Lernszenarien in diesem Sinne entwickelt und ich bekam direkt die Einladung, eigene Ideen für die Chatbot-Oberfläche aufzubereiten und zu teilen. Das ist toll und bestärkend in Hinblick auf gemeinsame, pädagogische Gestaltungsmöglichkeiten und ich freue mich, dass ich immer mehr Menschen wahrnehme, die Ähnliches versuchen.

    Bleibt das Argument, dass das alles aber leider viel zu langsam sei und KI-Technologie eben nicht auf die bundesdeutsche Kultusbürokratie warten würde. Einerseits klingt dieser Einwand sehr plausibel, wenn man sich anschaut, in welch schneller Geschwindigkeit KI-Modelle trainiert und mit immer mehr Möglichkeiten ausgestattet werden. Auf der anderen Seite kann gerade deshalb ein immer schnellerer Wettlauf aus meiner Sicht nicht die Lösung sein. Gute, weil nachhaltige, soziale und demokratische Zukünfte entstehen dann, wenn wir sie gemeinsam gestalten. Und in Gestaltung kommen wir nicht, wenn wir hinterherrennen, ohne uns zu verständigen, was wir überhaupt wollen und wo es hingehen soll.

    Zur Gestaltung gehört für mich dann ganz zentral die Frage der Nachhaltigkeit: Wenn festgestellt wird, dass AIS.chat weniger kann als andere Tools, dann sollten wir aus meiner Sicht vor allem fragen, welche Fähigkeiten tatsächlich pädagogisch sinnvoll und gesellschaftlich wünschenswert sind. Braucht es z.B. schnelle und fancy KI-gestützte Bild- und Videogenerierung, die erhebliche Ressourcen verschlingt? Oder kann es nicht auch eine bewusste politische und pädagogische Entscheidung sein, KI-Technologie weniger auf Lärm und Effekthascherei auszurichten – was bei profitgetriebenen Modellen in der Natur der Sache liegt – und mehr auf die Möglichkeiten der Mustererkennung und in diesem Sinne auf eine Spiegel- und Lernfunktion?

    Noch grundsätzlicher wird es, wenn wir die Ebene der Infrastruktur in den Blick nehmen. Hier wünsche ich mir von uns allen ein deutlich mutigeres Weiterdenken. Wenn wir nämlich weiterhin auf eine investorengetriebene Infrastruktur setzen, bei der dann als Folge notwendigerweise menschliche Bedürfnisse schon bei der Entwicklung technischer Anwendungen direkt auf ihre Verwertbarkeit hin abgeklopft werden, dann öffnet sich eben gerade nicht die Perspektive einer gemeinwohlorientierten Technologie. AIS.chat ist hier aus meiner Sicht noch zu wenig als Alternative angelegt. Es liegt aber an uns, ob wir uns – gerade im damit verbundenen größeren Projekt AIS – viel stärker als bisher auf dezentrale und schnittstellenermöglichende Lösungen hin orientieren.

    Um zu verdeutlichen, wie weit ein solches Denken reichen könnte: Mehrere Bildungseinrichtungen in einer Kommune könnten sich zusammenschließen und ein solarbetriebenes Rechenzentrum mit eigenen Servern entwickeln, auf denen lokale KI-Modelle laufen, die spezifisch angepasst werden können. Solch ein dezentraler und selbst verantworteter Ansatz klingt vielleicht erst einmal sehr weit von der Realität entfernt. Wir können aber genau in solche Richtungen am besten dann erste Schritte gehen, wenn wir Digitalisierung ganz bewusst als gesamtgesellschaftlichen Lernprozess und Gestaltungsherausforderung sehen, zu der wir insbesondere in der Pädagogik einen Beitrag leisten können, anstatt weiter profitgetriebenen, solutionistischen Technologie-Versprechen hinterherzujagen, die wir für eine l(i)ebenswerte Welt nicht brauchen.

    Wenn wir Digitalisierung als gemeinsamen Lern- und Gestaltungsprozess begreifen, dann ist AIS.chat genau der Ort, an dem sich diese Haltung einüben lässt. Genau deshalb lohnt es sich aus meiner Sicht, sich einzubringen statt mit Zynismus und Abwendung zu reagieren.

    Für mich gilt deshalb: Gut, dass es AIS.chat gibt! Lasst uns das Projekt nutzen, um KI-Technologie für die Bildung demokratisch, gemeinwohlorientiert und in öffentlicher Verantwortung zu entwickeln.

    #DigitaleMündigkeit #KünstlicheIntelligenzKI
  8. OpenCode: KI-Agenten mit mehr digitaler Mündigkeit

    Bereits vor einem Jahr habe ich mir einen eigenen KI-Server aufgesetzt und die Anleitung dazu geteilt. Ich nutzte dazu Ollama und OpenWebUI als Open-Source-‚Hülle‘, über die ich Schnittstellen zu KI-Sprachmodellen herstellen konnte. Das hat für mich im Hinblick auf eine digital-mündige KI-Nutzung zwei entscheidende Vorteile:

    1. Ich konnte und kann mir diese Umgebung so einrichten, wie ich das möchte: Welche Temperatur soll das KI-Sprachmodell in einer Interaktion nutzen? Welche spezifischen Anweisungen sollen berücksichtigt werden? Welche Dateien will ich als Basis einspeisen und darauf Bezug nehmen? Anders als bei einer Nutzung von Plattformen wie ChatGPT oder Claude sind all diese Dinge auf meinem eigenen Server gespeichert.
    2. Ich konnte und kann Open-Source-Modellen wie Mistral den Vorzug gegenüber proprietären Modellen geben. In der Praxis bedeutet das, dass ich für den überwiegenden Teil meiner KI-Chats das lokal auf meinem Server installierte Mistral nutzte. Erst wenn ich merkte, dass ich bei manchen Herausforderungen nicht weiterkomme, wechsle ich das Modell und nutzte dann eine Schnittstelle zu einem proprietären KI-Modell, in letzter Zeit meistens eines der Anthropic-Modelle. Ich habe dazu alle Modelle über OpenRouter gebündelt zur Verfügung.

    Diese Installation ist immer noch cool und hilfreich, wenn es um die Interaktion mit KI-Sprachmodellen geht, und ich kann sie weiterhin empfehlen. Seit Anfang dieses Jahres experimentiere ich nun aber zunehmend mit sogenannten KI-Agenten.

    Von KI-Sprachmodellen zu KI-Agenten

    Der Begriff ‚KI-Agent‘ führt aus meiner Sicht vielfach zu falschen Assoziationen – und die geteilten Einsatzzwecke solcher KI-Agenten tun ihr Übriges. Schnell erhält man dann den Eindruck, dass diese KI-Agenten völlig autonom irgendwelche Aufgaben für einen erledigen, z. B. mithilfe bereitgestellter Kreditkartendaten und einem Zugriff zum Internet eine komplette Reise für die Sommerferien planen, während ich mich schon vorab entspannen kann. Während so etwas vielleicht theoretisch möglich ist, dürfte für alle offensichtlich sein, dass das Risiko für Missbrauch und Fehler bei solch einem Ansatz sehr hoch ist und die Nutzung von KI-Agenten in solch einer Art und Weise nicht empfehlenswert ist. Ganz unabhängig davon, ob ich solch eine Nutzung überhaupt für mich will.

    Ich definiere KI-Agenten für mich stattdessen als ‚KI-Technologie, der ich Zugriff auf bestimmte Anwendungen auf meinem Rechner geben kann‘. Ganz konkret sieht das so aus, dass ich zum Beispiel einen Ordner auf meinem Laptop neu anlege, in diesen Ordner ein Video kopiere und dann an den genutzten KI-Agenten den Prompt schreibe, dass das Video transkribiert und dazu ein H5P-Inhalt erstellt werden soll. Das Tool wird dann nach weiteren Berechtigungen fragen (z. B. den Zugriff zu meiner Transkriptionssoftware oder den Zugriff zum Code-Verzeichnis von H5P im Internet). Ich kann jeweils immer prüfen, ob ich diesen Zugriff gewähren will. Wenn ja, dann bestätige ich das und das Tool arbeitet entsprechend weiter.

    Ich kommuniziere mit solch einem KI-Agenten im Terminal (= in der Konsole des Rechners), was für Menschen, die das ansonsten gar nicht tun, wahrscheinlich deutlich komplizierter klingt, als es real ist. Denn sobald ich den KI-Agenten darin installiert habe, was meistens nur ein einziger Befehl ist, kann ich dann auch im Terminal mit normaler menschlicher Sprache chatten, so wie ich das auch mit einem klassischen KI-Sprachmodell tun würde. Es gibt zusätzlich einzelne Befehle. In diese kann ich mich dann aber nach und nach und Schritt für Schritt einarbeiten.

    Möglichkeiten zur Nutzung von KI-Agenten

    Für mich hat sich die Art und Weise, mit KI-Technologie zu arbeiten, mit solchen KI-Agenten sehr verändert, und ich nutze sie inzwischen häufiger als klassische Sprachmodelle.

    Hier sind ein paar Einsatzzwecke:

    • Ich lade eine Sammlung an Inhalten in einen Ordner, die wir bei einem Workshop erarbeitet haben – und lasse mir diese clustern und sortieren.
    • Ich lasse einen heruntergeladenen Moodle-Kurs entpacken und arbeite dann an einer Neugestaltung/Aktualisierung.
    • Ich erstelle Texte für einen Flipped-Inhalt bei einem Lernangebot – und lasse daraus eine statische Website erstellen. (Dazu habe ich einen vorbereiteten ‚Skill‘, also eine Anweisung, was mir bei solchen Aufgaben übergreifend wichtig ist, z.B. ein bestimmtes CSS verwenden, möglichst keine externen Einbettungen, ein einmal geschriebenes Impressum immer wieder nutzen …)
    • Ich habe Freude bei der Gestaltung von Internetquatsch in Form von statischen Websites, die ich dann z. B. über GitLab, GitHub oder Codeberg online stellen kann.
    • Ich passe das Theme in einem CMS wie Publii oder einem Wiki wie dem DokuWiki an, so dass es für einen bestimmten Einsatzzweck von mir passt.

    Das ABER …

    Ich erlebe diese und weitere Einsatzzwecke als spannend und hilfreich und habe Freude beim Erkunden. An dieser Stelle kam dann aber bisher das große ‚Aber‘ für mich. Denn um diese Möglichkeiten zu nutzen, musste ich mich bisher für einen KI-Agenten-Anbieter entscheiden. Ich hatte Claude Code gewählt. Das funktionierte technisch gut; ich fand es aus der Perspektive der digitalen Mündigkeit aber nicht sinnvoll, weil ich ja eigentlich sehr bewusst versucht hatte, mich nicht in die Plattform eines Anbieters hineinziehen zu lassen, sondern mindestens jederzeit zwischen unterschiedlichen Anbietern wechseln zu können und – noch besser, wo möglich – lokal zu arbeiten bzw. Open-Source-Modelle zu nutzen.

    Offensichtlich standen andere Menschen vor dem gleichen Problem wie ich – und es gibt eine Lösung: OpenCode!

    Die Alternative: OpenCode

    OpenCode ist ein Open-Source-Tool, das – ähnlich wie Ollama und OpenWebUI bei meinem KI-Server – eine offene Software für die Nutzung und Einrichtung von KI-Agenten bietet. Das Tool wird auf dem eigenen Rechner installiert. Jederzeit kann dann zwischen unterschiedlichen Anbietern hin- und hergewechselt werden. Und ich kann das Tool auch mit lokalen Modellen verbinden. Von dem Anbieter gibt es mit OpenCode Zen auch ein kuratiertes Set an KI-Agenten-Modellen. Diese sind – anders als meine bisherige OpenRouter-Schnittstelle – auf Agentenmodelle spezialisiert. Ähnlich wie bei OpenRouter zahle ich dann auch hier für verwendete Tokens.

    Während die Einrichtung meines eigenen KI-Servers durchaus voraussetzungsreich war, ist OpenCode in der Installation nicht schwieriger als die Installation z.B. von Claude Code.

    Die Schritte sind:

    1. Du öffnest dein Terminal (= die Konsole, das schwarze Fenster, in das man Befehle eingeben kann.).
    2. Du gibst den Befehl zur Installation ein, den du hier findest.
    3. Du startest das Programm mit dem Befehl opencode.
    4. Du wählst aus, mit welchen Modellen du es verbinden willst, indem du den Befehl /connect eingibst. Für den Start fand ich die Verbindung mit Zen super. Das konnte ich einfach auswählen und mir dann zur Verbindung einen API-Code von der Website kopieren.
    5. Danach kannst du in das gewünschte Verzeichnis wechseln – und so wie gewohnt chatten.

    Meine bisherigen Erkundungen finde ich sehr zufriedenstellend. Ich werde berichten, welche Erfahrungen ich weiter damit mache. Eine Installation und ein Ausprobieren kann ich schon jetzt sehr empfehlen, und ich wünsche dir viel Freude dabei!

    #DigitaleMündigkeit #KünstlicheIntelligenzKI
  9. Dritte Orte im digitalen Raum

    Ich war dieses Jahr nicht bei der re:publica – und schaue mir gerade nachträglich einige Aufzeichnungen an. Sehr inspirierend und wertvoll zum Weiterdenken auch für meinen Kontext der Lerngestaltung finde ich diesen Impuls von Ralf Stockmann. Er stellt darin den Ansatz der Berliner Bibliotheken vor, die lokale Communities als ‚dritte Orte‘ auch in den Online-Raum zu erweitern und dafür eine erweiterte und angepasste Version von Discourse zu verwenden.

    https://youtu.be/PuLvBOmt3dE

    Ich finde daran besonders gut:

    1. Die sehr direkt Verbindung zwischen vor Ort und online. Der erste Zugang in den Online-Raum passiert direkt ausgehend vom physischen Raum.
    2. Der Ansatz, dass es nicht um ‚die nächste große Plattform geht‘, sondern eben um eine bewusste, soziale Gestaltung des Online-Raums mit realen, sozialen Verbindungen.
    3. Die vielen Möglichkeiten zur Gestaltung, die sich eröffnen. Anstatt doch direkt wieder in eine pasiv-konsumierende Rolle zu rutschen.

    Vielen Dank fürs Teilen!

    #DigitaleMündigkeit #OnlineLernen
  10. Das war ein feiner Workshop gestern beim Career Service an der @tudresden!

    12 Studis aus allen möglichen Fachrichtungen haben mit mir die Welt des Online-Datenhandels kennengelernt. In der Vorstellungsrunde sollten sie mal tippen, welche App auf ihren Handys wohl am neugierigsten ist.

    Nach einem kurzen Einstieg zu Privatsphäre im Netz und dem "Ich hab ja nichts zu verbergen"-Thema, haben wir geklärt, was Tracking eigentlich ist, was der eigene Browser so über einen selbst verrät, wie Apps Daten an Dritte senden und wie man sichtbar macht, welche Tracker man eigentlich auf dem eigenen Handy hat. @fdroidorg kennen sie nun, ebenso @exodus und den #DiDay.
    Zum Schluss konnten dann alle ihre Einschätzung vom Anfang über die neugierigen Apps selbst überprüfen (stimmte alles ;-)).

    Insbesondere das Ausprobieren kam gut an, damit man sich bei diesem Thema nicht so hilflos und ausgeliefert fühlt.

    #Datenschutz #Medienkompetenz #Datenhandel #Databroker #Tracking #digitaleMündigkeit #Privacy

  11. Answer Engine Optimization (AEO) – oder: Next Level Bullshitting

    Nach der Suchmaschinenoptimierung – kurz SEO für englisch Search Engine Optimization – gibt es im Kontext von KI eine neue Variante der Optimierung der eigenen Online-Präsenz. Die ‚Maschinenantwortoptimierung‘, abgekürzt AEO für englisch: Answer Engine Optimization. Dazu passt, dass auch die bisherigen Anbieter von Internetsuchen, allen voran Google, eine Umorientierung vorhaben. Anstelle der bisherigen Suche nach Begriffen und Anzeige von Websites soll – zumindest den Ankündigungen zufolge – ein AI-Chat der Standard-Zugang zu Online-Inhalten sein.

    AEO ist dabei nur einer von mehreren Begriffen für diese neue Perspektive. Andere sprechen von Generative Engine Optimization (GEO), LLM Optimization (LLMO) oder AI Visibility Optimization. Ich verwende im Folgenden AEO, weil es mir recht passend beschreibt, was damit intendiert ist – eben eine Optimierung der eigenen Online-Präsenz in den Antworten von Maschinen.

    Wichtig ist dabei dann noch eine Differenzierung. Antworten in einem KI-Chat können auf zwei Wegen erfolgen:

    1. Die Online-Inhalte sind in den Trainingsdaten eines KI-Modells integriert. Dann hilft eine kurzfristige Optimierung natürlich nicht.
    2. Die Online-Inhalte sollen in einer KI-Live-Suche gefunden werden. Dazu sind bisherige AEO-Tools vor allem ausgelegt.

    Ich plädiere im Folgenden dafür, den – in meinen Augen – reichlich absurden AEO-Zirkus nicht mitzumachen, sondern besser an Alternativen für ein offenes Internet zu arbeiten. Um das zu begründen, habe ich mir AEO aber genauer angeschaut. Mir hilft ein Blick in die Funktionsweise und ein direktes Ausprobieren, um mich zu so einer Entwicklung zu orientieren und dann das eigene Handeln ausrichten zu können.

    Was macht AEO?

    Bei SEO ging es darum, dass die Inhalte, die man ins Internet stellt, von Suchmaschinen möglichst gut gefunden werden. Ich habe mich damit nie systematisch beschäftigt, aber fand das grundsätzlich eine sinnvolle Sache. Denn wenn Maschinen meine Inhalte gut finden können, dann kann ich darüber wiederum mit meinen Inhalten Menschen erreichen, weshalb ich die Inhalte ja überhaupt teile.

    Vor diesem Hintergrund war ich gegenüber AEO grundsätzlich aufgeschlossen, habe mir beispielsweise auch bereits so genannte Grounding-Pages auf meiner Website eingerichtet, die für KI-Sprachmodelle optimiert sind und Infos zu meiner Person und dem eBildungslabor maschinenoptimiert zur Verfügung stellen. Mit solchen Schritten kann ich in einem veränderten Internet erreichen, dass meine Inhalte bei anderen Menschen ankommen. Soweit zumindest die Theorie.

    Wie sieht AEO in der Umsetzung aus?

    Ich habe mir als eines von mehreren AEO-Tools das Angebot von HubSpot angeschaut, das die AInauten in ihrem Newsletter recht begeistert weiterempfohlen haben.

    Durch dieses Tool klickt man sich relativ schnell durch. Name und Website und Funktion (bei mir: Freiberuflerin) können eingetragen werden oder werden direkt aus der Mailadresse extrahiert. Dann habe ich die Möglichkeit, noch alternative Namen einzugeben, und alles Weitere wird dann erst einmal automatisiert generiert. Im Einzelnen:

    • Wer meine Haupt-Konkurrenten sind (der Vorschlag war hier sehr spaßig: H5P, Moodle und oncampus – also alles Initiativen und Angebote, die ich aktiv und vernetzt nutze)
    • Was meine Angebote und Zielgruppen sind
    • Mögliche Prompts dazu, die Menschen bei KI-Sprachmodellen dazu eingeben könnten

    Das Tool testet dann in verschiedenen Sprachmodellen, ob diese nach Eingabe der entwickelten Prompts mich in ihren Antworten erwähnen. Wenn also z. B. jemand die Frage eingibt: „Ich suche kreative Methoden für mehr Interaktion beim Online-Lernen?“ Dann könnte es ja sein, dass in der Antwort irgendein Blogbeitrag aus dem eBildungslabor auftaucht, den ich in der Corona-Zeit geschrieben habe.

    Mein schneller Test war hier recht deutlich: Meine Inhalte scheinen bisher kaum den AEO-Standards zu entsprechen. Es gab in den verschiedenen, exemplarischen Antworten immer überhaupt keine Treffer. Das ist natürlich immer nur eine Annäherung, weil es ja statistische Antworten sind und meine Website in einem weiteren Versuch dann rein gewürfelt werden könnte. Die Tendenz ist erst einmal trotzdem ziemlich deutlich.

    Damit wird dann der nächste Part des Programms initiiert: Das Tool macht mir sehr konkrete Vorschläge, welche Inhalte ich publizieren könnte, um AEO besser zu entsprechen. Bei der Variante der Blogbeiträge hätte ich hier direkt die Möglichkeit, mir einen möglicherweise AEO-hilfreichen Beitrag direkt von einem KI-Sprachmodell schreiben zu lassen.

    Genau diese Orientierung brachte mich dann dazu, das Ganze für mich mit ‚Next Level Bullshitting‘ zu titulieren. Denn ich befürchte, dass genau das die Folge sein wird: Menschen klicken sich durch das Tool und generieren dann mithilfe der Anregungen tendenziell völlig beliebige Online-Inhalte, um genau damit dann besser in KI-Antworten gelistet zu werden.

    Wie ist diese Entwicklung einzuschätzen?

    Ich bringe eine grundsätzliche Aufgeschlossenheit für ‚Online-Kommunikation vermittelt über Maschinen‘ mit. Die AEO-Entwicklung erscheint mir allerdings absurd, weil – noch viel mehr als zuvor in vielen Bereichen schon SEO – auf eine entkontextualisierte Vermarktung von Produkten im Online-Raum gezielt wird, wobei alles bei zentralen Plattformen zusammenlaufen könnte, deren intransparente Algorithmen dann eben für den Preis von Sichtbarkeit bedient werden können. Allerdings nur mit Sichtbarkeit innerhalb des Modells: Ob mit der Anzeige dann auch ein Klick auf meine Website erfolgt, ist mindestens deutlich weniger wahrscheinlich als bei einer bisherigen Anzeige in der Suche, da meine Inhalte ja schon ausgespielt werden.

    Noch viel mehr als bisher scheint es das Ziel zu sein, Inhalte dafür zu generieren, dass eine wie auch immer geartete Sichtbarkeit oder Reichweite ermöglicht wird.
    Ich möchte mich in diese Logik nicht hinein begeben und ich denke, dass es dringend Energie und Aktivität für Alternativen braucht. Gerade jetzt, wo die Plattformlogik tendenziell tatsächlich in eine absurde Selbstreferenzialität kippt, scheint mir auch viel ‚fruchtbare Erde‘ und grundsätzliche Aufgeschlossenheit bei immer mehr Menschen für solche Alternativen vorhanden.

    Was sind Alternativen?

    Eine alternative Internetkommunikation beinhaltet für mich drei wichtige zur AEO-Logik veränderte Orientierungen:

    1. Es geht um gestaltete und kontextualisierte Räume: Das, was ich ins Internet stelle, ist nicht einfach ein Inhalt im Sinne eines vermarktbaren Produkts. Vielmehr ist z. B. meine Website ein gestalteter Online-Raum, dem ich einen bestimmten Kontext gebe und in den ich Menschen einlade. Solch ein Ansatz ermöglicht Vielfalt und ernsthafte Auseinandersetzung mit geteilten Inhalten.
    2. Es geht um Verbindung und Beziehung: Meine Alternative sind natürlich keine isolierten Silo-Inhalte. Ganz im Gegenteil: Der Grundgedanke des Internets ist für mich Verbindung und Vernetzung. Wenn das aber tatsächlich so funktionieren soll, dass Vielfalt aufgegriffen und wertgeschätzt und wirksam werden soll, dann geht das nicht monopolisiert, sondern dezentral und über Schnittstellen.
    3. Es geht um sinnhaftes Handeln: Ausgangspunkt für jede Kommunikation und damit auch für Online-Kommunikation ist für mich das ‚Wozu?‘. Ich teile Online-Inhalte als Freiberuflerin natürlich immer auch, um potentiell gefunden zu werden und somit bezahlte Aufträge zu erhalten, von denen ich leben kann. Dieses Ziel lässt sich für mich aber nicht trennen von meinem grundsätzlichen Anliegen, mit meiner Arbeit, meinem Wirken und damit auch mit dem Teilen von Online-Inhalten einen Unterschied zu machen hin zu einer l(i)ebenswerten Welt. Gerade angesichts zunehmender Krisen in unserer Gesellschaft erscheint mir solch ein ausgerichtetes Handeln unerlässlich.

    Sinnhaftes Handeln in einer technologisch fortgeschrittenen und zunehmend KI-geprägten Welt bedeutet für mich nicht technologische Abwehr, sondern dass ich technologische Potentiale erkenne und versuche, sie zur Entfaltung zu bringen.

    Während bei SEO vielleicht noch ein bisschen die Ideen eines offenen Netzes zumindest durchschimmerten, scheint mir das bei AEO nun praktisch gar nicht mehr gegeben zu sein. Es gilt deshalb, an Alternativen zu arbeiten, diese vorzuleben und auch andere dazu zu befähigen. Das sind dann wenig spektakuläre, aber aus meiner Sicht sinnhafte Schritte: eine eigene Website, Verständnis und Lernen zu Dezentralität sowie auf Schnittstellen setzen und diese bedienen. Pionierarbeit sehe ich zu Letzterem zurzeit im Fediverse, aber auch in Projekten wie z. B. NOSTR.

    Ich freue mich, dass ich immer mehr Menschen und Initiativen wahrnehme, die solche Entwicklungen voranbringen. Du bist herzlich eingeladen, anstatt weiter Energie in ein immer absurderes, monopolisiertes Internet zu stecken, solche Entwicklungen mit zu unterstützen. Gerade wenn der Preis dafür ist, dass AEO-Tools dir dann ‚0 % KI-Sichtbarkeit‘ bescheinigen. :-)

    Wenn wir jetzt eigene, selbst-gehostete Online-Räume, föderierte Verbindungen und direkte Kanäle pflegen, andere dazu befähigen und auf diese Weise ein immer vielfältigeres dezentrales Online-Ökosystem entwickeln, bei dem es nicht um abstrakte Reichweite, sondern sinnhafte Wirkung geht, dann arbeiten wir nicht gegen Technologie, sondern für eine alternative, nämlich gemeinwohlorientierte und gemeinschaftlich genutzte Technologie, was Grundlage sein kann für bessere Zukünfte.

    #DigitaleMündigkeit #KünstlicheIntelligenzKI
  12. „Ich hielt das Fediverse lange für Nerd-Spielzeug. Keine Promis, keine Reichweiten-Maschinerie, keine „Personal Brands“. Doch genau das wurde plötzlich seine Stärke: Während US-Medien einknickten, Threads leer blieb und Bluesky Twitter cosplayte, wurde das Fediverse für viele zum einzigen Ort für verlässliche Infos, kuratierte Links und echte Diskussionen. Spannender Perspektivwechsel.“

    #Fediverse #Mastodon #SocialMedia #DigitaleMündigkeit #Dezentralisierung

    matduggan.com/boy-i-was-wrong- (Artikel in englischer Sprache)

  13. Digitale Mündigkeit, informationelle Selbstbestimmung, individuelle und gesellschaftliche digitale Souveränität, das ist das Gegenteil von Überwachung, Ausforschung und Manipulation. Die digital unterstützte Repression und Kontrolle sind Teil des Kriegs Reich gegen Arm, den die Reichen und Mächtigen begonnen haben, um die Krise des Kapitalismus und des Kapitals zu bewältigen. Deshalb ist digitale Mündigkeit, wie sie auch beim DIDay / Digitalen Unabhängigkeitstag gecoacht wird, Klassenkampf. Nicht jede.r DIDay-Aktive wird das so sehen, und es ist auch nicht erstrebenswert, am DIDay unbedingt diese Diskussion zu führen. Am ersten Sonntag im Monat konzentriere ich mich auf die praktische Hilfe. Das ist bloß die Bedeutung, die der DIDay für mich hat.

    #DiDay #DigitaleMündigkeit #Schnüffler #Datenhunger #Ozapftis #Intelligenz #DigitaleSelbstverteidigung #InformationelleSelbstbestimmung #Überwachung #Manipulation #Ausforschung #DigitalerUnabhängigkeitstag #DUTgemacht #DIDit

    di.day

  14. Hunde schnüffeln beim Hallo-Sagen an ihren Körpern, besonders am Hintern des anderen Hundes. Dabei erfahren sie, wie der.die Andere drauf ist.

    Unsere datenhungrigen Behörden und Unternehmen weltweit würden den gesamten Überwachungsapparat abschaffen und nur noch an unseren Hintern schnüffeln, wenn sie dabei so viel erfahren könnten wie die Hunde. Wäre ein noch schlimmerer Albtraum als die gegenwärtige und wahrscheinliche zukünftige Realität, aber rein visuell finde ich die Vorstellung zum Lachen.

    #DiDay #DigitaleMündigkeit #Schnüffler #Datenhunger #Ozapftis #Hunde #Intelligenz #DigitaleSelbstverteidigung #InformationelleSelbstbestimmung #Überwachung #Manipulation #Ausforschung #DigitalerUnabhängigkeitstag #DUTgemacht #DIDit

    di.day

  15. Super-simple Wikis für Zusammenarbeit: ein Klassiker-Werkzeug, das immer noch hilfreich ist

    In Hinblick auf die technologische Entwicklung ist gerade eine spannende Zeit: Während viele Menschen schon länger mit Wissensmanagement-Anwendungen im Sinne eines ‚Second Brain‘ experimentieren, kommt nun noch die Möglichkeit dazu, in solche Systeme auch KI-Technologie zu integrieren oder KI-Tools direkt zu einer Art Bibliothekar dieses zweiten Gedächtnisses zu machen. Die Idee für die Interaktion mit der KI ist dann nicht mehr: „Hier sind viele Dateien. Ich stelle dir Fragen dazu!“, sondern vielmehr: „Hier sind viele Dateien. Bringe sie in ein vernetztes System und verknüpfe jeweils neue Inhalte sinnvoll damit.“ Auf diese Weise bekommen – so die Idee und Hoffnung – KI-Tools eine Art Gedächtnis und sind nicht mehr nur Archiv, das jedes Mal wieder von Neuem durchsucht wird.

    Angesichts solcher Entwicklungen mutet es ziemlich altertümlich an, nach wie vor zugleich auch ein super-simples, weil statisches Wiki-System für die Zusammenarbeit zu verwenden. Ich empfinde das aber gar nicht als Gegensatz. Vielmehr erscheint es mir gerade in solch einer Situation, wo es mehr und mehr automatisierte und aufwendige Technologie gibt, die vielfach zugleich monopolisiert ist, umso wichtiger, immer wieder die Perspektive von selbst-gehosteten und einfachen Tools aufzumachen, die insbesondere Einzelpersonen ohne größere Infrastruktur oder Organisation im Hintergrund und mit wenig Zeit online stellen und warten können. Das ist dann eine sehr realistische und konkrete Perspektive für digitale Mündigkeit.

    Solche Wikis nutze ich – ich habe nachgerechnet – tatsächlich schon seit rund 20 Jahren in der Zusammenarbeit mit anderen Menschen. Die Software hat sich in dieser Zeit verbessert: die Installation ist deutlich niederschwelliger, es braucht nur noch minimale Infrastruktur-Anforderungen und die Arbeit damit funktioniert auch mobil. Die grundsätzlichen Prinzipien sind aber gleich geblieben. Und ich finde Wikis immer noch und vielleicht gerade wegen so vieler weiterer und neuerer Möglichkeiten sehr hilfreich!

    In diesem Blogbeitrag möchte ich deshalb genauer vorstellen, was ein Wiki in der Zusammenarbeit genau leistet und wie es eingesetzt werden kann, welche Software ich empfehle und wie sich diese installieren lässt.

    Spoiler vorab: Du brauchst nicht einmal 10 Minuten, um dir ein selbst-gehostetes Wiki Open Source und datenschutzkonform aufzusetzen. Und die anschließende Zusammenarbeit und der kollaborative Aufbau einer Wissensbasis kann damit sehr gut funktionieren!

    Was ist ein Wiki und warum ist es cool?

    Was ein Wiki ist, muss dank der großen Bekanntheit der Wikipedia kaum mehr erklärt werden. Im Kern handelt es sich einfach um eine erweiter- und veränderbare Sammlung mit Inhalten, die beliebig miteinander verlinkt werden können.

    Ich mag an Wikis vor allem diese Aspekte:

    • Offen und flexibel: Ein neu installiertes Wiki gibt erst einmal gar nichts vor. Ich kann mir eine eigene Startseite gestalten und genau die Struktur und den Rahmen aufsetzen, die wir für unsere jeweilige Zusammenarbeit brauchen. Und in diesem Rahmen kann dann kollaborativ ganz wunderbar viel entstehen.
    • Relativ selbsterklärend: Tools zur Zusammenarbeit setzen voraus, dass alle Beteiligten in einer Gruppe diese Tools auch gut und niederschwellig nutzen können. Bei einem Wiki scheint mir diese Anforderung relativ gut erfüllt zu sein. Wer Wikis noch nicht kennt, muss eigentlich nur verstehen, dass alle an allen Inhalten schreiben können, immer frühere Versionen gespeichert werden und vor allem dass sich interne und externe Links meist mit eckigen Klammern setzen lassen, um Verknüpfungen herzustellen.
    • Offene Formate: In einem Wiki sind Inhalte in offenen Dateiformaten gespeichert. Ich kann sie jederzeit auch aus dem Wiki herausholen und anderweitig weiter nutzen. Damit ist nicht nur die Sicherung von Dateien völlig unproblematisch. Sie lassen sich zugleich auch in vielen anderen Tools nutzen. Ohne solche offenen Formate wäre ein Aufbau einer Wissensbasis deutlich weniger nachhaltig.

    Neben dieser Nutzungsebene mag ich aus Perspektive von digitaler Mündigkeit und Offenheit, dass es eine Vielzahl von Open Source Software gibt, die eine realistische Selfhosting-Option ermöglicht.

    Das bedeutet: Ich muss keine aufwendige Serverkonfiguration kennen oder eine Datenbank einrichten. Sobald ich ein bisschen Webspace zur Verfügung habe, kann ich die Software hochladen und kann dann direkt an die Einrichtung gehen. Auch eine Sicherung des Wikis ist dank der offenen Dateistruktur sehr unkompliziert.

    Wie geht das genau?

    Meine Lieblings-Software für ein Wiki ist zurzeit die Open Source Software DokuWiki. Mit dieser funktioniert Installation und Nutzung genau wie oben beschrieben.

    Ganz konkret:

    • Du kaufst dir bei einem Hosting-Anbieter für rund einen Euro im Monat ein bisschen Webspace und bekommst von dort die Zugangsdaten. Wenn du ohnehin schon eine Webseite hast, kannst du das Wiki einfach in einem Unterordner installieren. Du benötigst keine Datenbank.
    • Du lädst dir die Software von der DokuWiki-Website herunter und dann auf deinen Webspace hoch. Dazu kannst du ein Tool wie FileZilla verwenden.
    • Du öffnest den entsprechenden Ordner auf der Website und ergänzt beim Link /install.php.
    • Das öffnet einen Konfigurations-Screen, in dem du die Sprache (das DokuWiki gibt es in zahlreichen Sprachen und auch auf Deutsch, sogar mit Unterscheidung zwischen formeller und informeller Sprache) auswählst und einen Admin-Zugang mit Passwort bestimmst. (Der Admin-Zugang kann insbesondere weitere Benutzer anlegen. Außerdem kannst du entscheiden, ob das Wiki ganz offen genutzt werden kann (= alle können auch ohne Registrierung alles bearbeiten) oder ein geschützter Raum mit begrenztem Zugang sein soll. Auch die Lizenz der Inhalte ganz festgelegt werden.)
    • Anschließend kannst du die Datei install.php löschen – und direkt damit starten, dein Wiki einzurichten.

    Wie lässt sich solch ein Wiki nutzen?

    Nach der Installation können beliebig viele Benutzer-Accounts angelegt werden. Alternativ kann man auch eine offene Registrierung erlauben.

    Vor dem Teilen mit der ganzen Gruppe empfiehlt es sich, ein bisschen vorzustrukturieren. Standardmäßig nehme ich zum Beispiel gerne eine Aktuelles-Rubrik auf, ein Log von Besprechungen/Treffen, einen Gedankenspeicher oder eine Linksammlung.

    Wenn ein Wiki vor allem auch als ‚Master-Doc‘, d.h. zur auch synchronen Zusammenarbeit z.B. für Mitschriebe bei Treffen verwendet werden soll, bietet sich eine Kombination mit einem Etherpad an. Das kann so aussehen, dass z.B. das jeweils nächste Treffen einer Gruppe zu einem Etherpad verlinkt wird. Dort kann dann mitgeschrieben werden. Nach dem Treffen wird der Mitschrieb ins Wiki übertragen und somit gesichert.

    Wer auch im Bereich von Videokonferenzen Open Source Software und hier ganz konkret BigBlueButton verwendet, kann auf diesen Schritt auch verzichten, denn BigBlueButton verfügt mit den ‚geteilten Notizen‘ über eine kollaborative Mitschreibmöglichkeit.

    Das Vorgehen ist dann:

    • direkt synchron in der Videokonferenz mitschreiben
    • Mitschrieb sichern
    • ins Wiki übertragen.

    Fazit

    Das war eine schnelle Darstellung und unbedingte Empfehlung gerade in kleineren Projekten eine Wiki-Nutzung in Erwägung zu ziehen. Diese Empfehlung bedeutet nicht, dass es nicht auch viel neue und spannende Tools gibt, mit denen es sich zu experimentieren lohnt. Wenn wir aber eine realistische Umsetzungsperspektive für digital-mündige Technologienutzung haben wollen, dann braucht es aus meiner Sicht zugleich noch viel mehr solcher Möglichkeiten, die eben ganz niederschwellig auch ‚ganz normalen‘ Menschen, ohne Infrastruktur einer größeren Organisation und ohne große Zeitkapazitäten für Sicherungen und Serverkonfiguration möglich ist. Ein Wiki auf Basis der DokuWiki Software ist dazu aus meiner Sicht eine sehr gute Möglichkeit!

    Aus all diesen Gründen kann ich dir das Ausprobieren sehr empfehlen. Schreibe mich gerne an, falls du Fragen dazu hast oder Unterstützung benötigst.

    #DigitaleMündigkeit #Tools
  16. Wozu lernen wir – und für und mit welcher Technologie?

    Ich habe vor kurzem in meinem Blog aufgeschrieben, dass ich die ‚Nordsterne‘ in pädagogischen Transformationsdebatten oft zu eng gefasst finde. Denn diese betrachten in der Regel die Frage: Wie wollen wir lehren und lernen? Ich habe als Ergänzung formuliert: Wozu lernen wir? Als Antwort habe ich die Perspektive einer l(i)ebenswerten Welt vorgeschlagen, die sich aus dem ‚Woher?‘ ergibt – den in uns angelegten menschlichen Potenzialen, die es in Lernräumen zu entfalten gilt.

    In diesem Blogbeitrag möchte ich gerne noch einen Schritt weiter gehen und diese Perspektive eines doppelt erweiterten Nordsterns mit meinem Fokus auf Bildung und Digitalisierung zusammenbringen.

    Warum ein pädagogischer Nordstern unter Einbezug von Digitalisierung?

    Debatten zu Bildung und Digitalisierung beschränken sich erfreulicherweise schon lange nicht mehr nur um ‚Lehren und Lernen mit digitalen Tools‘. Stattdessen gerät zusätzlich immer mehr auch die Perspektive von ‚Lehren und Lernen in einer digital-geprägten Welt‘, also die Frage der Lernkultur, in den Blick. Relativ unverbunden steht dann aber oft daneben, dass wir Digitalisierung auch als Lerngegenstand betrachten und reflektieren sollten. Dieser Aspekt ist bleibt dann meist nur ein kleines Add-On.

    Aus meiner Sicht gehören diese drei Ansätze zusammen, sollten verbindend reflektiert werden und führen zu der dann um den Fokus der Digitalisierung erweiterten Nordstern-Frage:

    Wozu lernen wir – und für und mit welcher Technologie?

    Diese Erweiterung ist aus meiner Sicht vor allem deshalb relevant, weil wir Bildung ausgehend von unserer zunehmend digital-geprägten Gesellschaft gestalten. Das hat eine doppelte Konsequenz:

    1. Es gilt zu klären, welche Digitalisierung wir uns in und für eine l(i)ebenswerte Welt vorstellen. Wir müssen also mit dem gesamtgesellschaftlichen Nordstern auch einen Technologie-Nordstern entwickeln.
    2. Es gilt zu reflektieren, wie die gegenwärtige Ausgestaltung von Digitalisierung unsere Handlungsmöglichkeiten hin zur Realisierung dieser Nordsterne behindert oder auch befördern kann.

    Welche Digitalisierung wollen wir für eine l(i)ebenswerte Welt?

    Eine l(i)ebenswerte Welt ist eine Welt, in der Leben entfaltet ist und sich weiter entfalten kann. Damit das gelingt, müssen wir uns an ‚organischer Intelligenz‘ orientieren.

    Organische Intelligenz funktioniert nicht über den Versuch der Kontrolle, sondern durch Verbindung. Das Bild ist hier ein Garten, in dem ich etwas pflanzen und das Wachstum der Pflanzen unterstützen kann. Es ist keine Fabrik, in der nach festen Vorgaben etwas durchgeplant entsteht.

    Die vorherrschende Digitalisierung funktioniert dagegen überwiegend konträr zu diesem Leitbild der Lebendigkeit. Sie ist geprägt von Plattformen, die Silos darstellen, deren Infrastruktur auf Verwertbarkeit durch Monopolisierung und Machtkonzentration zielt. Pädagogisch ist hierbei relevant, dass genau diese Grundlage auch einen Einfluss auf unsere Nutzungspraxis hat: Diese Form der Digitalisierung unterstützt und befördert Individualisierung, Konkurrenzdenken und Standardisierung.

    Für eine Digitalisierung, die sich an organischer Intelligenz orientiert und diese befördert, wäre stattdessen Dezentralität der für mich wichtigste Hebel von Veränderung.

    Hintergrund ist hier, dass Dezentralität im Kern bedeutet, nicht auf Kontrolle zu setzen, sondern Verbindung und Offenheit zu ermöglichen. Wenn Digitalisierung deshalb statt auf Monopolisierung auf Dezentralisierung setzen würde, dann würde sie sich sehr grundlegend verändern und ein verändertes, viel menschlicheres Handeln ermöglichen.

    Im Fediverse habe ich das wie folgt beschrieben:

    Dezentralisierung würde in diesem Sinne ermöglichen:

    • Communities statt Plattformen
    • Schnittstellen und Interoperabilität statt abgegrenzten Silos
    • Demokratie, Mündigkeit und Selbstbestimmung statt Machtkonzentration, Abhängigkeit und Manipulation
    • Gemeinschaftlichkeit statt Individualisierung
    • Kooperation statt Konkurrenz
    • Gemeinwohl statt Verwertbarkeit
    • Demut und Bedeutung statt Ego und Lärm
    • Vielfalt statt Standardisierung
    • Sicherheit und Experimentieren statt Angst und Druck

    Ich finde an solchen Gegenüberstellungen mit einer pädagogischen Brille spannend, dass wir auf der Ebene von Haltung und Werten sehr viele Überschneidungen dazu sehen, wie wir uns nicht nur eine bessere Technologie, sondern auch eine bessere Bildung vorstellen. Es steckt also viel Synergiepotential darin, diese wünschenswerten Systemveränderungen verbindend zu betrachten. Und es wird deutlich, dass eine pädagogische Perspektive für die Gestaltung einer veränderten Technologie sehr viel beizutragen hat.

    Wie nutzen und gestalten wir Digitalisierung, um zu einer l(i)ebenswerten Welt zu gelangen?

    Wenn der Nordstern klarer wird, dann schließt sich die Frage an, wie wir ihn erreichen können. Herausfordernd ist dabei in der Bildung vor allem die extreme Ambivalenz, die mit der vorherrschenden, gegenwärtigen Technologie verbunden ist:

    1. Auf der einen Seite steht die vorherrschende Digitalisierung wie oben dargestellt konträr zu Lebendigkeit und damit zu menschlichen Potenzialen, die wir im Interesse einer l(i)ebenswerten Welt eigentlich zur Entfaltung bringen wollen.
    2. Auf der anderen Seite ermöglicht selbst diese Digitalisierung, weil ihr Geschäftsmodell ist, menschliche Bedürfnisse anzusprechen, immer wieder flüchtige Einblicke und auch konkrete Möglichkeiten, sie im Sinne von organischer Intelligenz zu nutzen. Beispielsweise kann ich die Mustererkennung von monopolisierten KI-Modellen als Hilfe für Gruppenprozesse nutzen oder für mich hilfreiche soziale Verbindungen über proprietäre Social Media Plattformen aufbauen.

    In dieser Ambivalenz ist pädagogisch für mich ein Dreiklang nötig:

    1. Akzeptanz: Anerkennen, dass es Technologie in ihrer gegenwärtigen Form gibt und dass sie Teil unserer Lebenswelt – der Lehrenden wie auch der Lernenden – ist.
    2. Reflexion: Am besten ausgehend von konkreter Nutzung Räume schaffen, um zu reflektieren, wo Technologie uns manipuliert und wo wir uns deshalb vor ihr schützen sollten und wie uns trotz alledem in manchen Bereichen ein ‚Hacking‘ gelingen kann.
    3. Alternativen: Perspektiven für eine veränderte Technologie öffnen, die genau mit den Mustern bricht, die wir oben als konträr zum Prinzip der Lebendigkeit identifiziert haben.

    Je verbindender wir diese drei Herausforderungen aufgreifen und je mehr wir sie mit der Nordstern-Orientierung verbinden, umso wirkungsvoller.

    Für den zurzeit viel diskutierten Bereich der künstlichen Intelligenz kann das beispielsweise bedeuten:

    • KI nicht verbieten/aussperren, sondern in der Bildung zu einem Thema machen.
    • Über KI-Nutzung reflektieren, bewusst auch Lernen ohne KI ermöglichen und uns zugleich an einer kontra-intuitiven KI-Nutzung versuchen, die KI nicht als Antwortmaschine, sondern als Resonanzmaschine versteht.
    • Auf die Suche begeben, wo es eine andere Form von KI gibt, was für mich vor allem offene KI-Modelle sind und zugleich auch nicht-generative KI, die in der gegenwärtigen Diskussion fast gar nicht im Blick ist.

    Am Beispiel von Social Media könnte es bedeuten:

    • Social Media als Teil von Lebensrealität anerkennen und mit einem offenen Blick Nutzungspraktiken und Gewohnheiten verstehen und besprechen.
    • Räume schaffen, um zu reflektieren, was Social Media mit uns macht und gemeinsam zu Vereinbarungen zu kommen, wo Abschalten allen Beteiligten besser tut. Und zugleich erkunden, wo Social Media zum Beispiel Verbindung und Zuspruch ermöglichen kann.
    • Alternativen wie das Fediverse stärken und gerade im Bildungskontext erfahrbar machen.

    Fazit: Pädagogische Diskussion erweitern

    Ich freue mich darauf, diese erweiterten Perspektiven, die jede einzelne für sich sicher nicht neu sind, mit solch einem verbindenden Nordstern-Blick im Kontext von Bildung und Digitalisierung aufzugreifen und zu gestalten.

    Durch die Entwicklungen rund um KI sehe ich in diesem Bereich aktuell einen wirkungsvollen Hebel. um Veränderungen anstoßen zu können, weil sich angesichts von immer leistungsfähigeren Maschinen gesamtgesellschaftlich immer drängender die Frage stellt, was uns als Menschen ausmacht – und damit auch, welche Digitalisierung wir eigentlich wollen. Ich denke, dass wir mit einem Blick auf Lernen als Entwicklung, Ermöglichung und Ermächtigung in einer gemeinschaftlichen Perspektive hier vieles beitragen können.

    Wer am 18. April bei der edunautika in Hamburg ist: Sehr gerne möchte ich dazu in einer Session gemeinsam weiter denken!

    #DigitaleMündigkeit #KünstlicheIntelligenzKI
  17. Beim Gautinger Internettreffen

    Immer mal wieder hatte ich in den letzten Jahren vom Gautinger Internettreffen gehört oder gelesen. Dieses Jahr war ich selbst mit einem Impuls zu zukunftsgestaltendem Lernen dabei. Das Motto des diesjährigen Treffens lautete: digital und selbstbestimmt. Meine These dazu war:

    Digital und selbstbestimmt braucht ganzheitlich und verbunden.

    Ich habe mich dieser These in drei Schritten genähert:

    1. Ausgangspunkt war für mich die Möglichkeitsmut-Wippe: Um im Kontext technologischer Entwicklungen weder in naiven Optimismus noch in Bildungsalarmismus zu verfallen, hilft eine bewusste Verschiebung weg von Abwehr, Angst und Fatalismus, hin zu Akzeptanz, Neugierde und Gestaltungszuversicht.
    2. Diese Gestaltungszuversicht gerät allerdings unter Druck, wenn wir technologische Entwicklungen in ihrer Tiefe betrachten. Eine digitale Infrastruktur, die von Kommerzialisierung, Monopolisierung und Machtkonzentration geprägt ist, kann leicht das Gefühl von Ohnmacht erzeugen. Umso wichtiger ist es, sich klarzumachen: Diese Herausforderungen sind nicht nur äußere Bedingungen, denen wir ausgeliefert sind. Innere Entwicklung und äußere Veränderung hängen zusammen. Ohne ein ‚In die Zukunft lehnen‘ im Inneren bleibt auch Gestaltung von Technologie im Außen begrenzt.
    3. Auf diesem Weg können wir den Blick auf die DeepSkills richten, die uns als Menschen zur Verfügung stehen. Sie entstehen in Lernkontexten, die Ganzheitlichkeit und Verbundenheit ermöglichen.

    In diesem Sinne wird für mich verständlich, warum digital und selbstbestimmt ohne ganzheitliche und verbundene Lernprozesse nicht denkbar ist. Durch die so ermöglichte Entfaltung menschlicher Potenziale können Lernprozesse der Ermächtigung entstehen.

    Solche Lernprozesse sind natürlich kein Selbstläufer, aus denen automatisch eine bessere Bildung oder eine bessere Technologie entsteht. Wenn ich zum Beispiel als Pädagogin mit einem potenzialorientierten Blick auf Lernende schaue, dann kann ich in der Folge leicht in Konflikt mit der vorherrschenden Prüfungskultur geraten. Genau die so entstehenden Widersprüche können dann aber wiederum produktiv genutzt werden, um auch im Äußeren für Veränderungen einzutreten. Ohne die innere Entwicklung hin zu einem Growth Mindset hätte ich mich gar nicht auf diesen Weg gemacht.

    Was für die Gestaltung von Bildung gilt, gilt auch für die Entwicklung von Technologie. Mit Ganzheitlichkeit und Verbundenheit öffnen wir den Blick auf die Frage: Welche Technologie entwickeln wir für die Welt, die wir eigentlich wollen? Wir bleiben also nicht mehr bei der Frage stehen: Wie nutzen wir Technologie möglichst effizient innerhalb des bestehenden Systems?

    Spätestens dann wird deutlich, dass Technologie an dieser Stelle natürlich nur ein Ausschnitt ist. Wir können diese Herangehensweise insgesamt auf die Herausforderungen dieser Welt übertragen. Durch Entfaltung menschlicher Potenziale im Inneren im Sinne von Ganzheitlichkeit und Verbundenheit kommt eine bessere, weil l(i)ebenswerte Welt in den Blick.

    Im Ergebnis lässt sich dann sagen:

    Gute Pädagogik ist immer auch Aktivismus für eine bessere Welt!

    Herzlichen Dank für die Einladung und den schönen Austausch vor Ort in Gauting!

    Credits und zugleich Vertiefungs-Empfehlungen des Impulses waren:

    #DigitaleMündigkeit
  18. Kartenset: Grundrechte im Digitalen

    Im vergangenen Jahr war ich daran beteiligt, mit dem Bildungs-Team der Wikimedia ein Kartenset zum Thema ‚Grundrechte im Digitalen‘ zu konzipieren und zu erstellen. Inzwischen liegt das Ergebnis gestaltet und gedruckt vor und ich konnte es mir beim heutigen Gautinger Internettreffen auch selbst anschauen.

    Ich freue mich sehr, dass dieses Kartenset als offenes Bildungsmaterial veröffentlicht ist. Das bedeutet: Du kannst es dir auf der Website herunterladen und für deine Zwecke anpassen. Gedacht ist das Kartenset für einen haptischen Einsatz in offenen, austauschorientierten Lernprozessen. Vor diesem Hintergrund gibt es auf der Website auch die Möglichkeit, das Kartenset gedruckt zu bestellen.

    Was ist das für ein Kartenset?

    Das Kartenset besteht aus einer kurzen, didaktischen Handreichung, in der einige Inspirationen zu finden sind, wie mit den Karten gemeinsam gelernt werden kann. Der Fokus liegt hier auf der Methode des Kartenaustausch, um sich unterschiedliche Konzepte und Perspektiven im Austausch miteinander zu erschließen.

    Im Kartenset sind dafür drei Kartentypen enthalten:

    1. Basiskarten mit denen bestimmte Begriffe erklärt und mit einem Beispiel veranschaulicht werden. Dabei wird dann immer auch der Bezug zu den Grundrechten deutlich gemacht. Solche Begriffe sind z.B. Deep Fakes, Algorithmus, Bias, Barrierefreiheit oder Netzneutralität.
    2. Persona-Karten, in denen vielfältige Personas dargestellt werden, in deren Rolle im Austausch geschlüpft werden kann.
    3. Aktions-Karten mit Anregungen für umfangreichere Projekte.

    Zielgruppe des Kartensets sind Jugendliche und Erwachsene ab ca. 14 Jahren.

    Wie geht es damit weiter?

    Schön an der OER-Veröffentlichung des Kartensets ist, dass immer eine Weiterentwicklung möglich ist. Beim heutigen Workshop gab es insbesondere die Anregung, auch eine Version in leichter Sprache zu veröffentlichen oder noch die Kartenkategorie ‚Lebenswelt‘ zu ergänzen.

    Fazit

    Ich freue mich sehr, dass die Wikimedia dieses Thema aufgegriffen und das Material veröffentlicht hat. Ich selbst werde es sicher in der Erwachsenenbildung nutzen, um Grundlagenwissen zu dem Thema gemeinsam zu entwickeln. Falls das Material für deinen Kontext auch spannend sein kann, dann probiere es gerne aus. Viel Freude damit!

    Zum Kartenset bei der Wikimedia

    #DigitaleMündigkeit
  19. 5. DI.DAY in Erlangen im ZAM: mein Browser, das unbekannte Wesen

    3. Mai 2026, 15:00:00 CEST - GMT+2 - Hauptstraße 65-67, 91054 Erlangen, 65-67 Hauptstraße (Erlangen)

    f.termine.di.day/events/5ca1e0

  20. 4. DI.DAY in Erlangen im ZAM: Clouds aus regionaler Aufzucht?

    12. April 2026, 15:00:00 CEST - GMT+2 - Hauptstraße 65-67, 91054 Erlangen, 65-67 Hauptstraße (Erlangen)

    f.termine.di.day/events/1e4a59

  21. Eine eigene Website – ohne Wartungsaufwand

    Ich finde es eine gute, hilfreiche und sinnvolle Sache, wenn Menschen, die kluge Gedanken haben, diese nicht nur für sich behalten und sie auch nicht nur über Social Media Plattformen publizieren, wo sie nicht nachhaltig auffindbar sind, keine Hoheit darüber besteht und sie vor allem auch sehr schlecht referenziert werden können. Stattdessen rege ich in solchen Fällen sehr gerne und häufig an, sich doch eine eigene Website einzurichten.

    Mein Standard-Vorschlag hierzu war eine WordPress-Website. Wenn es die eigene Website ist, dann nutzt man hier nicht WordPress.com, sondern lädt sich über wordpress.org die Open Source Software herunter und installiert sie auch auf einen Server. Ich habe das Vorgehen in diesem Beitrag ausführlich beschrieben. Der große Vorteil an WordPress ist, dass die Software direkt viele hilfreiche Funktionalitäten mitbringt. Im Blog können z.B. direkt Kommentare freigeschaltet werden. Außerdem lassen sich über WordPress unter anderem Formulare anlegen oder auch H5P-Inhalte erstellen und teilen. So etwas kann im pädagogischen Alltag sehr hilfreich sein.

    In letzter Zeit habe ich nun aber immer öfter die Erfahrung gemacht, dass WordPress für viele Menschen auch keine sinnvolle Wahl ist. Insbesondere dann, wenn Menschen sehr eingespannt sind, wahrscheinlich eher weniger bloggen, sondern einfach nur immer mal wieder etwas online stellen wollen, aber ansonsten mit der Website möglichst wenig zu tun haben wollen. In diesem Fall ist WordPress eine schlechte Wahl, weil es schon nötig ist, dort regelmäßig drauf zu schauen, Updates zu installieren und die Seite (gerade wenn man Kommentare oder andere interaktive Möglichkeiten nutzt) im Blick zu behalten.

    Auf eine eigene Website muss dann trotzdem nicht verzichtet werden, aber ich würde dann nicht WordPress, sondern besser ein statisches Website-Tool empfehlen. Am liebsten mag ich hier gerade Publii, weil es grundsätzlich sehr benutzerfreundlich und nicht zu nerdig angelegt ist, so dass auch technisch nicht sehr affine Menschen damit zurecht kommen sollten.

    Beim Einrichten solcher Websites kommt man schnell zu einer gewissen Routine und übersieht, dass beim ersten Mal doch mehr getan werden muss, als es sich für mich inzwischen anfühlt. Um die erstmalige Erstellung einer solchen Website für dich so einfach wie möglich zu machen, kommen hier die Schritte, die du nacheinander durchgehen kannst – inklusive einer offen nutzbaren Vorlage, um direkt ohne langes Einrichten mit der inhaltlichen Arbeit beginnen zu können:

    1. Domain und Webspace kaufen

    Für einen eigenen Ort im Netz benötigst du Webspace und eine Domain (= der Name, über den andere deine Website aufrufen können). Ich empfehle dazu, sich einen Account bei Hetzner anzulegen, dann das Webhosting Paket S auszuwählen, dort einen Namen festzulegen und die Domain einzugeben. Weitere Angaben braucht es nicht. Wenn die Domain noch frei ist, kann sie direkt bestellt werden. Jetzt braucht es 1-2 Stunden bis der Account und die Domain nutzbar sind. Du kannst in dieser Zeit direkt mit den nächsten Schritten weitermachen.

    2. Publii installieren

    Wir wollen die Website ja mit Publii bauen. Das ist ein Programm, über das du dann Inhalte für die Website schreiben kannst und von dort aus dann auch direkt auf den Webspace hochladen kannst. Damit du dieses Programm nutzen kannst, musst du es dir auf deinem Desktop-Gerät installieren. Du lädst es dir dazu von hier herunter passend zu deinem Betriebssystem und lässt dich durch den Installationsprozess führen. Dann kannst du das Programm öffnen.

    3. Website in Publii anlegen

    In Publii kommt dann jetzt der interessantere Part. Du kannst dir dort deine gewünschte Website anlegen. Um dir die ersten Schritte möglichst einfach zu machen, empfehle ich dir, deine Website nicht neu, sondern von einem Backup anlegen. Dazu lädst du dir hier diese Datei herunter und dann bei Publii rein.

    start-fuer-deine-websiteHerunterladen

    Also: ‚Create new Website‘ und dann ‚Install from Backup‘. Dann kannst du direkt den gewünschten Seitennamen angeben und mit einem bereits fertigen Rohgerüst starten. Du musst dann diese Schritte gehen:

    • Unter Site Settings deine Beschreibung eingeben.
    • Unter Author deinen Namen eintrage
    • Unter Theme unten bei Layout runterscrollen bis du zur Hero-Section kommst. Dort dann deinen Begrüßungstext eingeben. Unter Footer kannst du Accounts von Social Media eintragen.
    • Unter Pages bei Impressum und Datenschutz deine Kontaktangaben eingeben

    Danach kannst du zu Posts gehen und deinen ersten Beitrag schreiben.

    Nützlich ist noch der File-Manager, wenn du z.B. eine Präsentation oder eine andere Datei hochladen und dann in Posts oder Pages verlinken kannst. Du findest den File Manager unter Tools & Plugins.

    4. Mail und SSL Verschlüsselung

    Nun müssen wir deine Website noch ins Internet bringen. Zuerst einmal verschlüsseln wir dazu deine Domain. Das machst du in deinem Hetzner-Account. Du gehst dort zur Domain (nicht zum Account). Auf Einstellungen, ganz unten SSL. Dann Basic Zertifikat auswählen. Länge des Schlüssels nicht ändern. Rechts daneben den Pfeil zum Laden anklicken. Das braucht eine gute Minute. Dann darunter: HTTPS-Weiterleitung auf ein schieben.

    Wichtig: Dieser Schritt funktioniert erst, wenn deine Domain erreichbar ist. Das ist meist ca. 1-2 Stunden nach der Bestellung der Fall.

    Update: Wenn du vorher deine Domain irgendwo anders hattest und diese Domain umziehst, musst du zusätzlich noch den SSL-Manager öffnen und die Domain korrekt zuweisen. Wenn du die Domain aber neu kaufst, sollte alles automatisch funktionieren.

    Anschließend kannst du dir unter E-Mail noch direkt eine Mailadresse oder Weiterleitung zu deiner Domain anlegen.

    5. Publii mit Webspace verbinden

    Bei Hetzner findest du dann auch die Zugangsdaten, die wir jetzt für Publii zur Verbindung der erstellten Inhalte auf deinem Desktop mit dem Webspace brauchen. Dazu gehst du zum Account (also nicht mehr Domain). Du kannst da direkt in der Kopfzeile in den Breadcrumbs eins weiter vorne anklicken.

    Die Zugangsdaten findest du dann unter Einstellungen und Logindaten. Diese Sachen musst du dann bei Publii eingeben:

    • Dazu gehst du zu Server.
    • Dann SFTP auswählen.
    • Die Website-URL ist deine Domain.
    • Port müsste bei 22 sein. Also nicht ändern.
    • Server von Hetzner reinkopieren (z.B. wwwxxx.your-server.de oder etwas ähnliches).
    • Ebenso Loginname als Username und das Passwort.
    • ‚Always ask for password‘ kannst du ausgestellt lassen, wenn du auf deinem eigenen Gerät arbeitest.
    • Dann bei remote path eintragen: public_html/
    • Dann unten Test Connection.

    Wenn kein Fehler kommt: Save Settings.

    Jetzt fehlt dann nur noch die Übertragung. Dafür kannst du links unten ‚Sync your Website‘ wählen. Alles wird hochgeladen – und wenn du jetzt deine Website-Adresse im Browser öffnest, stehen deine Inhalte online. Du kannst jederzeit ändern/ ergänzen und dann einfach immer wieder syncen. Manchmal sind Dateien noch im Cache des Browsers und du siehst nicht direkt Änderungen.

    Geschafft! 🎉

    Ich wünsche dir viel Freude mit deiner Website. Melde dich gerne, wenn du nicht weiter kommst!

    #DigitaleMündigkeit
  22. Di.Day zu KI in Halle

    Heute war ich mit beteiligt, einen weiteren Raum für den Digital Independence Day bei uns in Halle (Saale) zu öffnen. Wir haben uns im Co-Working Space am Klaustor mit dem Thema Offenheit und KI auseinander gesetzt.

    Der Di.Day ist eine bundesweite Initiative: Jeden ersten Sonntag im Monat kommen Menschen zusammen, um ganz konkret für mehr digitale Unabhängigkeit aktiv zu werden.

    Bei uns war heute eine bunte Mischung an Menschen gekommen: Rentner, Lehrkräfte, medienpädagogisch tätige Menschen, Jugendliche … Meine Rolle habe ich darin gesehen, den Rahmen für das Gespräch zu setzen und zu halten. Wir haben dazu mit der Viereck-Methode zunächst als Blitzlicht gesammelt, was die Beteiligten an Infos mitbringen, welche Fragen sie haben und was sie zuversichtlich bzw. besorgt stimmt. Diese Aspekte konnten wir dann zunächst im Plenum bearbeiten, bevor es in kleine Gesprächs- und Erkundungsrunden ging.

    Gemeinsam haben wir auch festgehalten, dass es den Di.Day an diesem Ort auch zukünftig geben soll. Das nächste Mal (wegen Ostern) nicht am 1. Sonntag des April, sondern erst am 12. April 2026.

    Ich finde das eine sehr gute Sache. Es gibt wohl kaum etwas Sinnvolleres, was man in der gegenwärtigen Situation einer zunehmenden gesellschaftlichen Spaltung tun kann, als Räume zum Austausch und zum gemeinsamen Lernen zu öffnen und zu gestalten.

    #DigitaleMündigkeit
  23. Gemeinwohlorientierte Digitalpädagogik

    Erschließe dir den Beitrag mit KI-Interaktion!

    Wähle die Interaktion, die dich bei der Erschließung dieses Beitrags am meisten interessiert. Klicke auf den Button – ein vollständiger Prompt wird automatisch in deine Zwischenablage kopiert. Füge ihn dann in ein Sprachmodell deiner Wahl ein.

    Erkläre mir den Inhalt des Textes einfach und prägnant! Warum könnte dieser Beitrag für mich spannend sein? Was spricht gegen die Thesen dieses Beitrags? Gib mir drei Fragen für einen Austausch über den Beitrag Was wäre ein konkreter Schritt, den ich aufbauend auf diesem Beitrag angehen könnte?

    Hiermit möchte ich den Nordstern einer gemeinwohlorientierten Digitalpädagogik in die Debatte zu Bildung im digitalen Wandel einführen. Ich sehe den folgenden Beitrag dazu als ersten Aufschlag und freue mich über zusätzliche Perspektiven und gemeinsames Weiterdenken.

    Was ist und warum braucht es gemeinwohlorientierte Digitalpädagogik?

    Bildung findet heute zu einem großen Teil im Spannungsfeld zwischen vielfältigen Möglichkeiten und gesamtgesellschaftlichen Krisen statt. Aufgabe von Bildung ist es in dieser Situation insbesondere, zu gesellschaftlicher Handlungsfähigkeit zu ermutigen und zu ermächtigen. Das bedeutet konkret, dass Lernende angesichts der zahlreichen Krisen nicht mit Rückzug und Fatalismus reagieren, sondern bestärkt und befähigt werden, gemeinsam mit anderen für soziale, demokratische, friedliche und ökologische Veränderungen aktiv zu werden.

    Im Kontext der Digitalisierung ist das besonders relevant, denn gerade hier ist zwischen digitaler Utopie und digitaler Dystopie, die sich in der gesamtgesellschaftlichen Debatte munter abwechseln, kaum Raum, um ins Gestalten zu kommen. Gemeinwohlorientierte Digitalpädagogik eröffnet dazu einen Weg.

    Das Konzept hat dabei zwei wichtige Grundlagen:

    1. Digitalisierung wird nicht primär als Werkzeug eingeordnet, was es überwiegend individuell zu lernen und zu gestalten gilt. Stattdessen geht es um eine systemische Perspektive auf die Digitalisierung, die kollektives Lernen und Gestalten erfordert.
    2. Digitalisierung wird mit einer normativen Orientierung verbunden. Das Ziel ist die Erfüllung menschlicher Bedürfnisse und damit die Erweiterung von Gemeinwohl.

    Grundlegend für eine gemeinwohlorientierte Digitalpädagogik ist für mich, dass mit diesem Ansatz digitale Infrastruktur und Eigentum sowie die damit verbundenen Interessen in den Blick genommen werden. Das ist nötig, um eine grundlegende Alternative zur vorherrschenden Form der Digitalisierung zu eröffnen. Denn digitale Anwendungen werden in dieser vorherrschenden Gestaltungsform meist im Sinne einer solutionistischen Herangehensweise entwickelt, die erstens Technik anstelle sozialer Aushandlung als primäre Lösung für Herausforderungen einordnet und zweitens erkannte Bedürfnisse direkt auf ihre Verwertbarkeit hin abklopft. Digitalisierung wird mit dieser Herangehensweise somit vor allem als Möglichkeit verstanden, um Anwendungen zu entwickeln, die Profite versprechen und bestehende Macht- und Eigentumsstrukturen nicht antasten oder diese sogar noch weiter zementieren. Gemeinwohlorientierte Digitalisierung zielt stattdessen auf eine Digitalisierung, die der Allgemeinheit dient. Menschen können auf diese Weise tatsächlich zu Gestalter*innen ihrer (längst und immer mehr digital geprägten) Lebenswelt werden.

    Solche grundsätzlichen Änderungen brauchen kritisches Denken, Verlernen und Neulernen. Dazu ist Pädagogik erforderlich. Zugleich ermöglichen diese Änderungen dann wiederum pädagogische Perspektiven, die Lernenden Gestaltungsmacht für die Entwicklung wünschenswerter Zukünfte ermöglichen.

    Gemeinwohlorientierte Digitalpädagogik hat dabei Ähnlichkeit mit medienpädagogischen Ansätzen und insbesondere der kritischen Medienpädagogik. Als Bild eines Eisbergs dargestellt erweitert sie klassische Medienkompetenzmodelle (z. B. nach Dieter Baacke), die vor allem sichtbar-individuelle Handlungsebenen adressieren, um eine stärker strukturelle und systemische Perspektive. Es geht dann nicht mehr nur um das Verstehen und Reflektieren von Medien, sondern digitale Infrastrukturen, Macht- und Eigentumsstrukturen und ihre gesellschaftlichen Auswirkungen kommen stärker in den Blick. Bei Nutzung und Gestaltung von Medien wird auf souveräne und selbstbestimmte Nutzung digitaler Räume mit Blick auf die dahinterliegenden Strukturen gezielt und die aktive, gemeinwohlorientierte Mitgestaltung digitaler Infrastrukturen und Praktiken in den Fokus genommen.

    Gemeinwohlorientierte Digitalpädagogik hat für mich vor diesem Hintergrund zwei zentrale Dimensionen:

    • Sie ist erstens Lerngegenstand: Hier geht es darum, weg von einem Werkzeugverständnis der Digitalisierung hin zu einer systemischen Betrachtungsweise zu kommen. Es geht darum zu analysieren, zu reflektieren und Schritt für Schritt zu verstehen, wie die für uns sichtbare Digitalisierung durch die dahinterliegende Infrastruktur geprägt wird und diese zugleich politisch, ökonomisch und kulturell mitformt. Diese Perspektive ermöglicht es, ein Verständnis zu entwickeln, an welchen Hebeln eine gemeinwohlorientierte Digitalisierung ansetzen muss.
    • Sie ist zweitens Gestaltungsprinzip: Hier geht es darum, zu lernen und vor allem praktisch zu erkunden, wie Digitalisierung orientiert am Gemeinwohl gestaltet sein kann. Wie immer im Kontext der Digitalisierung geht es hier natürlich auch um technische Fragen (z.B. Wie baue ich einen eigenen Server auf?). Mindestens ebenso wichtig (und pädagogisch aus meiner Sicht wahrscheinlich noch relevanter) ist die Frage, welche Praktiken der Zusammenarbeit und der Gestaltung eine gemeinwohlorientierte Digitalisierung braucht. Hier lassen sich dann Ansätze wie Commons und Open Source, Kultur des Teilens, Open Educational Resources und Open Educational Practices und viele andere Ansätze aufgreifen und vertiefen.

    Der Kern all dieser Aktivitäten ist eine kollektive Herangehensweise. Denn Änderungen auf systemischer Ebene werden nicht individuell erreicht werden können.

    Genau dieser kollektive Ansatz ist es dann auch, der in der Pädagogik realistische Wege ausgehend vom Hier und Jetzt für die Ermächtigung und Ermutigung von Lernenden zu gesellschaftlicher Handlungsfähigkeit ermöglicht. Schulen und andere Bildungseinrichtungen können und sollten deshalb Treiber und Akteure einer gemeinwohlorientierten Digitalpädagogik sein.

    Leseempfehlung

    Einen ausgezeichneten Einstieg in das Thema der gemeinwohlorientierten Digitalpädagogik bekommst du über das Buch Broligarchie von Aya Jaff. Die große Stärke dieses Buches liegt für mich darin, dass Aya in dem Buch ihren eigenen Weg als Lernreise beschreibt. Sie war früher Teil der vorherrschenden Digitalszene. Ihr Buch ist nun weniger ein klassischer Aussteigerbericht (auch wenn das schon auch Teil ist), sondern Schritt für Schritt die Darstellung, wie und warum sie die damit verbundenen grundlegenden Widersprüche für sich reflektiert hat und wie sie damit beginnt, sich mit anderen zusammenzuschließen und Alternativen zu entwickeln.

    Das Buch ist dabei durchgängig klar und niederschwellig geschrieben. Sie beschönigt nicht, aber bleibt auch nicht bei der Beklagung des Ist-Zustands stehen, sondern macht Mut, sich einzubringen und aktiv zu werden.

    #DigitaleMündigkeit #OEROffenheit
  24. Das Netz ist politisch.

    Das Buch von @adfichter ist soeben eingetroffen. Mit Liebe verpackt von der Buchhandlung Bodmer.

    Jetzt erst mal gemütlich machen und mir einen Überblick verschaffen.

    #buch #lesen #analog #netzpolitik #digitalemündigkeit #digitalesouveränität #dnip

  25. Neues Jahr, neue Nerdigkeiten. 😊

    Tauscht euch mit uns aus über #DigitaleMündigkeit. Alle Kenntnis-Niveaus von null bis 1 sind herzlich willkommen. 😊

    Erste Themen: #Rädli, #DIDay, Nextcloud. Und, was ihr so mitbringt.

    📅 Freitag, 23.01.2026
    ⌚ ab 8:30 Uhr ist jemand da
    📍 Allee am Röthelheimpark 3B, #Erlangen (direkt durch die Drehtüren an der Bushaltestelle; ja, Drehtüren; nein, nicht die Bäckerei 😉)

  26. Dein persönlicher KI-Chatbot für Blogs: Open Source & lokal

    Immer wieder stoße ich im Internet auf das Angebot, mir eine ‚eigene KI‘ zu programmieren. Dahinter verbergen sich allerdings höchst unterschiedliche Dinge. In den meisten Fällen wird nicht tatsächlich ein KI-Modell programmiert. Stattdessen werden bestimmte Einstellungen zum Chatten festgelegt (z.B. ‚Gib möglichst kurze Antworten‘ oder ‚Sprich mich mit Du und Nele an‘) und/oder bestimmte Quellen festgelegt, auf die sich ein genutzter Chatbot in der Antwort beziehen soll.

    Der Fachbegriff für letzteres lautet: Retrieval Augmented Generation, abgekürzt RAG. Solch eine RAG-Herangehensweise ermöglicht es, einem KI-Modell eine bestimmte Datenbasis zur Verfügung zu stellen, auf die sich der Chatbot in seinen Antworten dann vorrangig beziehen soll.

    Ich habe RAG bereits vielfach auf meinem eigenen KI-Server ausprobiert. Meistens habe ich das aber auf einzelne Inhalte (z.B. auf einen bestimmten Blogbeitrag oder ein Transkript) bezogen, nicht auf umfangreichere Quellen wie z.B. alle Beiträge eines bestimmten Blogs. Genau dafür suchte ich jetzt nach einer Lösung. In diesem Zusammenhang wollte ich zugleich eine Lösung entwickeln, die auch andere möglichst ohne Kosten und umfangreiche technische Vorkenntnisse für sich nutzen können und die mit Open Source Modellen sowie unabhängig von proprietären KI-Plattformen funktioniert. Das Vorhaben ist somit – neben dem praktischen Nutzen – vor allem auch ein Projekt für mehr digitale Mündigkeit. Mein Vorgehen habe ich als Schritt-für Schritt Anleitung aufgeschrieben.

    Das klingt für dich interessant? Dann lies weiter und probiere die Anleitung sehr gerne für dich aus. Vielleicht hast du ja auch Lust, sie weiter zu verbessern!

    Grundsätzliche Schritte

    Unser Ziel ist ein RAG-Chatbot für Blog-Websites im Terminal deines Rechners (= dem schwarzen Fenster, in das sich Befehle eintippen lassen). Du kannst den Chatbot auch dann bauen, wenn du bisher noch nicht mit dem Terminal gearbeitet hast.

    Wir gehen in mehreren Schritten vor: Nach ein paar Vorbereitungen nutzen wir zuerst ein Programm, mit dem wir alle Beiträge von den von uns gewünschten Blogs herunterladen. Dabei überprüfen wir natürlich zunächst, ob die Blog-Inhaber*innen solch ein Scraping untersagen. Wenn nein, dann versuchen wir die Beiträge entweder über die REST-API (das funktioniert oft bei WordPress-Blogs; es ist ein maschinenlesbarer Zugang zu den Daten der Website) oder ansonsten über den RSS-Feed oder die Sitemap zu erhalten. Wir müssen dazu lediglich die URL (= die Internetadresse) der gewünschten Blogs eingegeben.

    Aus den eingesammelten Beiträgen gestalten wir dann – mit einem weiteren Open Source Programm – eine Vektor-Datenbank. Das ist eine komprimierte und maschinenlesbare Variante der Inhalte, die als Datenbasis von KI-Sprachmodellen genutzt werden kann. Diese Datenbank verbinden wir mit dem Open Source KI-Modell Mistral.

    Im letzten Schritt nutzen wir dann ein weiteres Programm – den eigentlichen Chatbot – um in die Kommunikation über die Beiträge in den Blogs zu gehen. Das funktioniert dann weiterhin über das Terminal, aber du wirst sehen, dass du im Ergebnis dann einen Bot gestaltet hast, der ähnlich wie andere KI-Chatbots menschliche Sprache auswerten und mit passenden Reaktionen – in unserem Fall mit den Inhalten basierend auf den eingepflegten Blogbeiträgen – antworten kann.

    Die folgende Anleitung stellt dir den Code für das ‚Beitragseinsammel-Programm‘ und das ‚Chatbot-Programm‘ zum direkten Weiternutzen zur Verfügung. Ich empfehle dir, erst einmal damit zu arbeiten. Später kannst du aber natürlich diese Programme auch anpassen und deinen Chatbot so noch sehr viel spezifischer für deine Bedürfnisse gestalten.

    Wozu das Ganze?

    Ich finde dieses Projekt aus mehreren Gründen ziemlich cool:

    1. Es ist ein offenes Projekt, das dir die Potenziale von Open Source Software zeigt und dir eine Alternative zu den proprietären KI-Plattformen ermöglicht.
    2. Es ist ein Projekt für mehr digitale Mündigkeit. Du verstehst und kannst erkunden, wie KI-Chatbots unter der Haube funktionieren.
    3. Du bekommst eine sehr nützliche Anwendung, mit der du Online-Inhalte aus von dir ausgewählten Blogs über eine Chatoberfläche in einem vernetzten Sinne ‚lesen‘ kannst.

    Schritt-für-Schritt Anleitung

    Insgesamt wirst du für die folgenden Schritte wahrscheinlich ungefähr eine Stunde Zeit brauchen. Du kannst jederzeit zwischendrin aufhören und wieder neu einsteigen.

    (Einschränkend möchte ich anmerken, dass ich die Schritte auf meinem Linux-Laptop durchgeführt habe. Ich gebe auch die entsprechenden Befehle für Windows und Mac an, aber habe diese nicht selbst getestet. Entstanden ist die Anleitung basierend auf meiner Ideen dazu, allgemeiner Internet-Recherche und Interaktion mit KI-Chatbots)

    Schritt 1: Vorbereitungen

    Um solch einen RAG-Chatbot für Blog-Websites im Terminal selbst zu basteln, sind zunächst drei Vorbereitungen nötig:

    1. Du solltest grundlegende Befehle im Terminal kennen.
    2. Du solltest dir Python installieren.
    3. Du solltest dir einen Mistral-API-Key besorgen.

    1. Grundlegende Befehle im Terminal kennen

    Zunächst zu den grundlegenden Befehlen im Terminal: Diese unterscheiden sich, je nachdem, ob du Linux, Windows oder einen Mac nutzt. Du findest das Terminal mit diesen Eingaben – oder auch einfach über eine Programmsuche:

    Linux:

    • Tastenkombination Strg + Alt + T oder
    • Suche nach „Terminal/ Konsole“ in deinen Anwendungen

    Windows:

    • Tastenkombination Windows-Taste + R, dann cmd eingeben und Enter drücken oder
    • Suche nach „Eingabeaufforderung“ bzw. „PowerShell“ im Startmenü

    Mac:

    • Tastenkombination Cmd + Leertaste, dann „Terminal“ eingeben oder
    • Gehe zu Programme → Dienstprogramme → Terminal

    Es öffnet sich dann ein kleines Konsolen-Fenster, über das du an deinen Rechner bestimmte Befehle senden kannst.

    (Ich habe die Terminal-Nutzung in den letzten Monaten übrigens sehr viel in Interaktion mit KI-Chatbots gelernt. Vor allem die Anthropic-Modelle funktionieren dazu aus meiner Sicht gut. Du kannst dann einfach im KI-Chat fragen, was der richtige Befehl für das Terminal ist, diesen dann im Zweifel noch einmal im Internet gegenchecken, dann eingeben – und wenn du dann einen irritierenden Output bekommst oder irgend etwas nicht funktioniert, diesen wiederum kopieren, mit dem KI-Chatbot teilen und dir erklären lassen.)

    Hier kommt eine kleine Basis-Übung, um das Prinzip des Terminals zu verstehen.

    Du brauchst dazu diese Befehle:

    Linux/Mac:

    • mkdir ~/Verzeichnis – um ein Verzeichnis zu erstellen
    • cd ~/Verzeichnis – um in das Verzeichnis zu wechseln
    • nano Dateiname – um eine Datei zu erstellen und/oder zu öffnen
    • Nach dem Eintragen dann Strg+O und Enter und Strg+X, um das Programm zu speichern und zu schließen

    Windows (PowerShell):

    • mkdir ~/Verzeichnis – um ein Verzeichnis zu erstellen
    • cd ~/Verzeichnis – um in das Verzeichnis zu wechseln
    • notepad Dateiname.txt – um eine Datei zu erstellen und/oder zu öffnen
    • Nach dem Eintragen über Datei → Speichern und dann Fenster schließen

    Windows (CMD):

    • mkdir %USERPROFILE%\Verzeichnis – um ein Verzeichnis zu erstellen
    • cd %USERPROFILE%\Verzeichnis – um in das Verzeichnis zu wechseln
    • notepad Dateiname.txt – um eine Datei zu erstellen und/oder zu öffnen

    Mit diesen Befehlen kannst du die Terminal-Nutzung testen:

    Für Linux/Mac gib im Terminal ein:

    mkdir ~/mein-testverzeichnis
    mkdir ~/mein-testverzeichnis

    Dann drücke Enter.

    cd ~/mein-testverzeichnis
    cd ~/mein-testverzeichnis

    Dann drücke Enter.

    nano testdatei.txt
    nano testdatei.txt

    Dann drücke Enter.

    Für Windows (PowerShell) gib im Terminal ein:

    mkdir ~/mein-testverzeichnis
    mkdir ~/mein-testverzeichnis

    Dann drücke Enter.

    cd ~/mein-testverzeichnis
    cd ~/mein-testverzeichnis

    Dann drücke Enter.

    notepad testdatei.txt
    notepad testdatei.txt

    Dann drücke Enter.

    Für Windows (CMD) gib im Terminal ein:

    mkdir %USERPROFILE%\mein-testverzeichnis
    mkdir %USERPROFILE%\mein-testverzeichnis

    Dann drücke Enter.

    cd %USERPROFILE%\mein-testverzeichnis
    cd %USERPROFILE%\mein-testverzeichnis

    Dann drücke Enter.

    notepad testdatei.txt
    notepad testdatei.txt

    Dann drücke Enter.

    Es öffnet sich ein Eingabefeld. Bei Linux/Mac ist das direkt im Terminal (nano-Editor), bei Windows öffnet sich der Notepad-Editor. Schreibe irgend etwas rein. Zum Beispiel:

    Hallo, ich erstelle eine Datei mithilfe des Terminals :-)

    Bei Linux/Mac: Dann Strg+O und Enter und Strg+X

    Bei Windows: Speichere über Datei → Speichern und schließe das Notepad-Fenster

    Nach dem Schließen gelangst du wieder zum ursprünglichen Terminal-Fenster zurück. Dass deine Befehle erfolgreich waren, siehst du, wenn du deine Ordnerverwaltung öffnest und darin tatsächlich den erstellten Ordner ‚mein-testverzeichnis‘ mit der Datei testdatei.txt und deinem Inhalt darin findest.

    (Ich fand das ziemlich großartig, als ich das zum ersten Mal gemacht habe. Wenn es auch dein erstes Mal ist, dann kannst du dich erst einmal freuen, dass du jetzt einen ziemlich coolen Weg kennst, um mit deinem Gerät zu kommunizieren! Wir werden das im Folgenden nutzen!)

    2. Python installieren

    Mit diesem Basiswissen können wir uns dann direkt an die Installation von Python machen. Das ist eine Programmiersprache, in der die Programme geschrieben sein werden, mit denen wir arbeiten.

    Ob Python bei dir ohnehin schon installiert ist, kannst du überprüfen mit diesem Befehl im Terminal:

    python --version
    python --version

    oder

    python3 --version
    python3 --version

    Wenn dann eine Versionsnummer zurückkommt (z.B. Python 3.13.11), ist Python installiert.

    Wenn nicht, dann kannst du es folgendermaßen installieren:

    Linux (Ubuntu/Debian):

    sudo apt update
    sudo apt install python3 python3-pip
    sudo apt updatesudo apt install python3 python3-pip

    Mac:

    brew install python3
    brew install python3

    (Falls Homebrew nicht installiert ist, folge dieser Anleitung.)

    Windows:

    1. Gehe auf https://www.python.org/downloads/
    2. Lade die neueste Version herunter
    3. Führe den Installer aus und setze unbedingt den Haken bei „Add Python to PATH“
    4. Klicke auf „Install Now“

    3. Mistral API-Key besorgen

    Als letztes benötigst du noch einen Mistral API Key. Mistral ist ein europäisches Open Source KI-Modell. Wir nutzen im Folgenden Mistral-small, was in einem begrenzten, aber für den persönlichen Gebrauch erfahrungsgemäß mehr als ausreichendem Umfang für Entwickler*innen kostenfrei zur Verfügung steht.

    (Mit dieser sehr umfangreichen, kostenfreien Entwicklungsmöglichkeit mit der Mistral-API verfolgt das Unternehmen übrigens eine aus meiner Sicht sehr stimmige Open Source Strategie: Je mehr Menschen mit der Mistral-API erkunden und ausprobieren, desto mehr Ideen und Produkte werden auf dieser Basis auch entwickelt, von denen einige dann später einen kostenpflichtigen Plan in Anspruch nehmen werden.)

    Um dir einen Mistral-API-Key zu besorgen, öffnest du diese Website, registrierst dich, gehst auf API und erstellst dir einen API-Key und speicherst ihn ab. Du kannst ihn z.B. „Blog-Chatbot“ nennen. Den API Key speicherst du dir ab, so dass du ihn später nutzen kannst.

    Wichtig: Du solltest den API-Key nicht öffentlich teilen!

    Schritt 2: Projekt aufsetzen

    In diesem Schritt sind wir weiter vorbereitend tätig, aber du kannst direkt deine Learnings aus Schritt 1 anwenden. Wir benötigen nämlich eine Projektumgebung (= einen Ordner auf deinem Rechner, in dem du deinen KI-Chatbot und die Inhalte speicherst). In diesem Ordner speicherst du dann deinen Mistral-API-Key und die weiteren, benötigten Programme.

    1. Projektverzeichnis erstellen

    Zunächst erstellen wir die Projektumgebung:

    Linux/Mac:

    mkdir ~/blog-chatbot-projekt
    cd ~/blog-chatbot-projekt
    mkdir ~/blog-chatbot-projektcd ~/blog-chatbot-projekt

    Windows (PowerShell):

    mkdir ~/blog-chatbot-projekt
    cd ~/blog-chatbot-projekt
    mkdir ~/blog-chatbot-projektcd ~/blog-chatbot-projekt

    Windows (CMD):

    mkdir %USERPROFILE%\blog-chatbot-projekt
    cd %USERPROFILE%\blog-chatbot-projekt
    mkdir %USERPROFILE%\blog-chatbot-projektcd %USERPROFILE%\blog-chatbot-projekt

    2. Virtuelle Umgebung erstellen

    Dann erstellen wir eine virtuelle Umgebung. Das ist sinnvoll, weil damit alle installierten Programme nur für dieses Projekt gelten und nicht mit anderen Python-Projekten auf deinem Rechner in Konflikt kommen können.

    Linux/Mac:

    python3 -m venv venv
    source venv/bin/activate
    python3 -m venv venvsource venv/bin/activate

    Windows (PowerShell):

    python -m venv venv
    .\venv\Scripts\Activate.ps1
    python -m venv venv.\venv\Scripts\Activate.ps1

    (Falls du eine Fehlermeldung bekommst, führe einmalig aus: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser)

    Windows (CMD):

    python -m venv venv
    venv\Scripts\activate.bat
    python -m venv venvvenv\Scripts\activate.bat

    Nach der Aktivierung siehst du (venv) am Anfang deiner Kommandozeile – das zeigt, dass die virtuelle Umgebung aktiv ist.

    3. API-Key speichern

    Jetzt speichern wir deinen Mistral-API-Key in einer Datei, die wir so erstellen, wie du es eingangs mit der Testdatei gelernt hast:

    Linux/Mac:

    nano .env
    nano .env

    Windows:

    notepad .env
    notepad .env

    Trage dann folgendes ein (ersetze YOUR_API_KEY durch deinen tatsächlichen Key, den du dir auf der Mistral-Website erstellt hast):

    MISTRAL_API_KEY=dein_api_key_hier
    MISTRAL_API_KEY=dein_api_key_hier

    Bei Linux/Mac: Speichere mit Strg+O, Enter, Strg+X

    Bei Windows: Speichere über Datei → Speichern und schließe Notepad

    4. Benötigte Programme installieren

    Jetzt installieren wir die Programme, die wir für unseren Chatbot brauchen:

    • chromadb – Die Vektor-Datenbank, in der die Blog-Beiträge gespeichert werden
    • sentence-transformers – Für die semantische Suche und Einbettung der Texte
    • requests – Um Webseiten abzurufen
    • mistralai – Das Programm, um mit der Mistral-API zu kommunizieren
    • python-dotenv – Um den API-Key aus der .env-Datei zu laden
    • feedparser – Um RSS-Feeds zu lesen
    • beautifulsoup4 – Um HTML-Inhalte zu verarbeiten

    Bei all diesen Programmen handelt es sich um Open Source Programme. Die Installation funktioniert über eine Befehlseingabe zur Installation (und etwas Zeit).

    Für alle Betriebssysteme (wenn virtuelle Umgebung aktiviert ist) gib diesen Befehl im Terminal ein:

    pip install chromadb sentence-transformers requests mistralai python-dotenv feedparser beautifulsoup4
    pip install chromadb sentence-transformers requests mistralai python-dotenv feedparser beautifulsoup4

    Dieser Installationsvorgang kann einige Minuten dauern. Lass das Terminal einfach arbeiten, bis du wieder die ursprüngliche Eingabeaufforderung siehst.

    Schritt 3: Blogs einsammeln und Vektordatenbank erstellen

    Mit der eingerichteten Basis aus Schritt 2 können wir jetzt das Blog-Einsammel-Programm erstellen und ausführen, so dass damit unsere Vektor-Datenbank erstellt wird. Ich nenne dieses Programm im Folgenden ‚Verwaltungsprogramm‘.

    1. Das Verwaltungsprogramm erstellen

    Du gehst wie folgt vor:

    Linux/Mac:

    nano blog_verwalten.py
    nano blog_verwalten.py

    Windows:

    notepad blog_verwalten.py
    notepad blog_verwalten.py

    Dann trägst du diesen Inhalt ein:

    import requests
    import chromadb
    from chromadb.utils import embedding_functions
    from bs4 import BeautifulSoup
    import feedparser
    from urllib.parse import urlparse
    from urllib.robotparser import RobotFileParser
    
    # Vektordatenbank-Setup
    client = chromadb.PersistentClient(path="./chroma_db")
    embedding_fn = embedding_functions.SentenceTransformerEmbeddingFunction(
        model_name="paraphrase-multilingual-MiniLM-L12-v2"
    )
    collection = client.get_or_create_collection(
        name="blog_posts",
        embedding_function=embedding_fn
    )
    
    def ist_gueltige_wahl(eingabe, optionen):
        """Prüft ob Eingabe eine gültige Menü-Option ist"""
        return eingabe in optionen
    
    def blog_existiert(blog_url):
        """Prüft ob Blog bereits in Datenbank ist"""
        alle_daten = collection.get()
        for meta in alle_daten['metadatas']:
            if meta['blog_url'] == blog_url:
                return True
        return False
    
    def pruefe_robots_txt(blog_url):
        """Prüft, ob Scraping erlaubt ist"""
        print("[1/5] Prüfe robots.txt... ", end="", flush=True)
        try:
            rp = RobotFileParser()
            rp.set_url(f"https://{blog_url}/robots.txt")
            rp.read()
            if rp.can_fetch("*", f"https://{blog_url}/"):
                print("✅ Scraping erlaubt")
                return True
            else:
                print("❌ Blog erlaubt kein automatisches Auslesen")
                print("\n💡 Respektiere die Vorgaben des Blogs!")
                print("   Alternative: XML-Export hochladen (falls du Zugriff hast)\n")
                return False
        except:
            # Keine robots.txt = erlaubt
            print("✅ Keine robots.txt (= erlaubt)")
            return True
    
    def hole_via_wordpress_api(blog_url):
        """Versucht Beiträge über WordPress REST API zu holen"""
        print("[2/5] WordPress REST API... ", end="", flush=True)
        alle_posts = []
        seite = 1
        try:
            while True:
                url = f"https://{blog_url}/wp-json/wp/v2/posts?per_page=100&page={seite}"
                response = requests.get(url, timeout=10)
                if response.status_code != 200 or not response.json():
                    break
                alle_posts.extend(response.json())
                seite += 1
    
            if alle_posts:
                print(f"✅ {len(alle_posts)} Beiträge gefunden")
                return [(p['title']['rendered'],
                        BeautifulSoup(p['content']['rendered'], 'html.parser').get_text(),
                        p['link'])
                       for p in alle_posts]
            else:
                print("❌ nicht verfügbar")
                return []
        except:
            print("❌ nicht verfügbar")
            return []
    
    def hole_via_rss(blog_url):
        """Versucht Beiträge über RSS-Feed zu holen"""
        print("[3/5] RSS-Feed Standard... ", end="", flush=True)
        feed_urls = [
            f"https://{blog_url}/feed/",
            f"https://{blog_url}/rss/",
            f"https://{blog_url}/feed.xml",
            f"https://{blog_url}/rss.xml"
        ]
    
        for feed_url in feed_urls:
            try:
                feed = feedparser.parse(feed_url)
                if feed.entries:
                    print(f"✅ {len(feed.entries)} Beiträge gefunden")
                    return [(e.title,
                            BeautifulSoup(e.get('content', [{}])[0].get('value', e.get('summary', '')), 'html.parser').get_text(),
                            e.link)
                           for e in feed.entries]
            except:
                continue
    
        print("❌ nicht verfügbar")
        return []
    
    def hole_via_rss_pagination(blog_url):
        """Versucht RSS mit Pagination"""
        print("[4/5] RSS mit Pagination... ", end="", flush=True)
        alle_posts = []
        seite = 2  # Seite 1 hatten wir schon
        try:
            while seite <= 50:  # Max 50 Seiten
                feed_url = f"https://{blog_url}/feed/?paged={seite}"
                feed = feedparser.parse(feed_url)
                if not feed.entries:
                    break
                alle_posts.extend(feed.entries)
                seite += 1
    
            if alle_posts:
                print(f"✅ weitere {len(alle_posts)} Beiträge")
                return [(e.title,
                        BeautifulSoup(e.get('content', [{}])[0].get('value', e.get('summary', '')), 'html.parser').get_text(),
                        e.link)
                       for e in alle_posts]
            else:
                print("❌ nicht verfügbar")
                return []
        except:
            print("❌ nicht verfügbar")
            return []
    
    def blog_hinzufuegen(blog_url):
        """Holt alle Beiträge von einem Blog"""
        # Prüfen ob Blog schon existiert
        if blog_existiert(blog_url):
            print(f"\n⚠️  Blog {blog_url} ist bereits gespeichert!")
            print("💡 Tipp: Erst löschen (Option 3), dann neu hinzufügen.\n")
            return
    
        print(f"\n📥 Versuche Beiträge von {blog_url} zu holen...\n")
    
        # 1. robots.txt prüfen
        if not pruefe_robots_txt(blog_url):
            return
    
        # 2-4. Verschiedene Methoden probieren
        alle_beitraege = []
    
        beitraege = hole_via_wordpress_api(blog_url)
        if beitraege:
            alle_beitraege.extend(beitraege)
        else:
            beitraege = hole_via_rss(blog_url)
            if beitraege:
                alle_beitraege.extend(beitraege)
                # Versuche noch mehr zu holen
                mehr = hole_via_rss_pagination(blog_url)
                if mehr:
                    alle_beitraege.extend(mehr)
    
        print(f"[5/5] Zusammenfassung... ", end="", flush=True)
    
        if not alle_beitraege:
            print("❌")
            print("\n❌ Keine Beiträge gefunden!\n")
            print("Mögliche Gründe:")
            print("• API/Feed sind deaktiviert")
            print("• URL ist nicht erreichbar")
            print("• Blog nutzt ungewöhnliche Struktur")
            print("\n💡 Alternative: XML-Export hochladen\n")
            return
    
        print(f"✅ {len(alle_beitraege)} Beiträge insgesamt")
        print("\n💾 Speichere in Datenbank...")
    
        for i, (titel, inhalt, link) in enumerate(alle_beitraege):
            collection.add(
                documents=[inhalt],
                metadatas=[{
                    "title": titel,
                    "link": link,
                    "blog_url": blog_url
                }],
                ids=[f"{blog_url}_{i}"]
            )
            if (i+1) % 50 == 0:
                print(f"  {i+1} Beiträge verarbeitet...")
    
        print(f"✓ Fertig! {len(alle_beitraege)} Beiträge von {blog_url} gespeichert.\n")
    
    def blogs_anzeigen():
        """Zeigt alle gespeicherten Blogs"""
        alle_daten = collection.get()
        if not alle_daten['metadatas']:
            print("\n❌ Noch keine Blogs gespeichert!\n")
            return
    
        blogs = {}
        for meta in alle_daten['metadatas']:
            blog = meta['blog_url']
            blogs[blog] = blogs.get(blog, 0) + 1
    
        print(f"\n📚 Gespeicherte Blogs ({len(blogs)}):")
        for blog, anzahl in sorted(blogs.items()):
            print(f"  • {blog} ({anzahl} Beiträge)")
        print()
    
    def blog_loeschen(blog_url):
        """Löscht alle Beiträge eines Blogs"""
        alle_daten = collection.get()
        ids_to_delete = [
            alle_daten['ids'][i] 
            for i, meta in enumerate(alle_daten['metadatas']) 
            if meta['blog_url'] == blog_url
        ]
    
        if not ids_to_delete:
            print(f"\n❌ Blog {blog_url} nicht gefunden!\n")
            return
    
        collection.delete(ids=ids_to_delete)
        print(f"\n✓ {len(ids_to_delete)} Beiträge von {blog_url} gelöscht.\n")
    
    def menu():
        while True:
            print("=" * 50)
            print("BLOG-CHATBOT VERWALTUNG")
            print("=" * 50)
            print("1 - Blog hinzufügen")
            print("2 - Blogs anzeigen")
            print("3 - Blog löschen")
            print("0 - Beenden")
            print("=" * 50)
    
            wahl = input("\nDeine Wahl: ").strip()
    
            if not ist_gueltige_wahl(wahl, ['0', '1', '2', '3']):
                print("\n❌ Ungültige Eingabe! Bitte wähle eine der Optionen (0-3).\n")
                continue
    
            if wahl == "1":
                url = input("Blog-URL (z.B. ebildungslabor.de): ").strip()
                blog_hinzufuegen(url)
            elif wahl == "2":
                blogs_anzeigen()
            elif wahl == "3":
                url = input("Welchen Blog löschen? ").strip()
                blog_loeschen(url)
            elif wahl == "0":
                print("\nTschüss! 👋\n")
                break
    
    if __name__ == "__main__":
        menu()
    import requestsimport chromadbfrom chromadb.utils import embedding_functionsfrom bs4 import BeautifulSoupimport feedparserfrom urllib.parse import urlparsefrom urllib.robotparser import RobotFileParser# Vektordatenbank-Setupclient = chromadb.PersistentClient(path="./chroma_db")embedding_fn = embedding_functions.SentenceTransformerEmbeddingFunction(    model_name="paraphrase-multilingual-MiniLM-L12-v2")collection = client.get_or_create_collection(    name="blog_posts",    embedding_function=embedding_fn)def ist_gueltige_wahl(eingabe, optionen):    """Prüft ob Eingabe eine gültige Menü-Option ist"""    return eingabe in optionendef blog_existiert(blog_url):    """Prüft ob Blog bereits in Datenbank ist"""    alle_daten = collection.get()    for meta in alle_daten['metadatas']:        if meta['blog_url'] == blog_url:            return True    return Falsedef pruefe_robots_txt(blog_url):    """Prüft, ob Scraping erlaubt ist"""    print("[1/5] Prüfe robots.txt... ", end="", flush=True)    try:        rp = RobotFileParser()        rp.set_url(f"https://{blog_url}/robots.txt")        rp.read()        if rp.can_fetch("*", f"https://{blog_url}/"):            print("✅ Scraping erlaubt")            return True        else:            print("❌ Blog erlaubt kein automatisches Auslesen")            print("\n💡 Respektiere die Vorgaben des Blogs!")            print("   Alternative: XML-Export hochladen (falls du Zugriff hast)\n")            return False    except:        # Keine robots.txt = erlaubt        print("✅ Keine robots.txt (= erlaubt)")        return Truedef hole_via_wordpress_api(blog_url):    """Versucht Beiträge über WordPress REST API zu holen"""    print("[2/5] WordPress REST API... ", end="", flush=True)    alle_posts = []    seite = 1    try:        while True:            url = f"https://{blog_url}/wp-json/wp/v2/posts?per_page=100&page={seite}"            response = requests.get(url, timeout=10)            if response.status_code != 200 or not response.json():                break            alle_posts.extend(response.json())            seite += 1        if alle_posts:            print(f"✅ {len(alle_posts)} Beiträge gefunden")            return [(p['title']['rendered'],                    BeautifulSoup(p['content']['rendered'], 'html.parser').get_text(),                    p['link'])                   for p in alle_posts]        else:            print("❌ nicht verfügbar")            return []    except:        print("❌ nicht verfügbar")        return []def hole_via_rss(blog_url):    """Versucht Beiträge über RSS-Feed zu holen"""    print("[3/5] RSS-Feed Standard... ", end="", flush=True)    feed_urls = [        f"https://{blog_url}/feed/",        f"https://{blog_url}/rss/",        f"https://{blog_url}/feed.xml",        f"https://{blog_url}/rss.xml"    ]    for feed_url in feed_urls:        try:            feed = feedparser.parse(feed_url)            if feed.entries:                print(f"✅ {len(feed.entries)} Beiträge gefunden")                return [(e.title,                        BeautifulSoup(e.get('content', [{}])[0].get('value', e.get('summary', '')), 'html.parser').get_text(),                        e.link)                       for e in feed.entries]        except:            continue    print("❌ nicht verfügbar")    return []def hole_via_rss_pagination(blog_url):    """Versucht RSS mit Pagination"""    print("[4/5] RSS mit Pagination... ", end="", flush=True)    alle_posts = []    seite = 2  # Seite 1 hatten wir schon    try:        while seite <= 50:  # Max 50 Seiten            feed_url = f"https://{blog_url}/feed/?paged={seite}"            feed = feedparser.parse(feed_url)            if not feed.entries:                break            alle_posts.extend(feed.entries)            seite += 1        if alle_posts:            print(f"✅ weitere {len(alle_posts)} Beiträge")            return [(e.title,                    BeautifulSoup(e.get('content', [{}])[0].get('value', e.get('summary', '')), 'html.parser').get_text(),                    e.link)                   for e in alle_posts]        else:            print("❌ nicht verfügbar")            return []    except:        print("❌ nicht verfügbar")        return []def blog_hinzufuegen(blog_url):    """Holt alle Beiträge von einem Blog"""    # Prüfen ob Blog schon existiert    if blog_existiert(blog_url):        print(f"\n⚠️  Blog {blog_url} ist bereits gespeichert!")        print("💡 Tipp: Erst löschen (Option 3), dann neu hinzufügen.\n")        return    print(f"\n📥 Versuche Beiträge von {blog_url} zu holen...\n")    # 1. robots.txt prüfen    if not pruefe_robots_txt(blog_url):        return    # 2-4. Verschiedene Methoden probieren    alle_beitraege = []    beitraege = hole_via_wordpress_api(blog_url)    if beitraege:        alle_beitraege.extend(beitraege)    else:        beitraege = hole_via_rss(blog_url)        if beitraege:            alle_beitraege.extend(beitraege)            # Versuche noch mehr zu holen            mehr = hole_via_rss_pagination(blog_url)            if mehr:                alle_beitraege.extend(mehr)    print(f"[5/5] Zusammenfassung... ", end="", flush=True)    if not alle_beitraege:        print("")        print("\n❌ Keine Beiträge gefunden!\n")        print("Mögliche Gründe:")        print("• API/Feed sind deaktiviert")        print("• URL ist nicht erreichbar")        print("• Blog nutzt ungewöhnliche Struktur")        print("\n💡 Alternative: XML-Export hochladen\n")        return    print(f"✅ {len(alle_beitraege)} Beiträge insgesamt")    print("\n💾 Speichere in Datenbank...")    for i, (titel, inhalt, link) in enumerate(alle_beitraege):        collection.add(            documents=[inhalt],            metadatas=[{                "title": titel,                "link": link,                "blog_url": blog_url            }],            ids=[f"{blog_url}_{i}"]        )        if (i+1) % 50 == 0:            print(f"  {i+1} Beiträge verarbeitet...")    print(f"✓ Fertig! {len(alle_beitraege)} Beiträge von {blog_url} gespeichert.\n")def blogs_anzeigen():    """Zeigt alle gespeicherten Blogs"""    alle_daten = collection.get()    if not alle_daten['metadatas']:        print("\n❌ Noch keine Blogs gespeichert!\n")        return    blogs = {}    for meta in alle_daten['metadatas']:        blog = meta['blog_url']        blogs[blog] = blogs.get(blog, 0) + 1    print(f"\n📚 Gespeicherte Blogs ({len(blogs)}):")    for blog, anzahl in sorted(blogs.items()):        print(f"  • {blog} ({anzahl} Beiträge)")    print()def blog_loeschen(blog_url):    """Löscht alle Beiträge eines Blogs"""    alle_daten = collection.get()    ids_to_delete = [        alle_daten['ids'][i]         for i, meta in enumerate(alle_daten['metadatas'])         if meta['blog_url'] == blog_url    ]    if not ids_to_delete:        print(f"\n❌ Blog {blog_url} nicht gefunden!\n")        return    collection.delete(ids=ids_to_delete)    print(f"\n{len(ids_to_delete)} Beiträge von {blog_url} gelöscht.\n")def menu():    while True:        print("=" * 50)        print("BLOG-CHATBOT VERWALTUNG")        print("=" * 50)        print("1 - Blog hinzufügen")        print("2 - Blogs anzeigen")        print("3 - Blog löschen")        print("0 - Beenden")        print("=" * 50)        wahl = input("\nDeine Wahl: ").strip()        if not ist_gueltige_wahl(wahl, ['0', '1', '2', '3']):            print("\n❌ Ungültige Eingabe! Bitte wähle eine der Optionen (0-3).\n")            continue        if wahl == "1":            url = input("Blog-URL (z.B. ebildungslabor.de): ").strip()            blog_hinzufuegen(url)        elif wahl == "2":            blogs_anzeigen()        elif wahl == "3":            url = input("Welchen Blog löschen? ").strip()            blog_loeschen(url)        elif wahl == "0":            print("\nTschüss! 👋\n")            breakif __name__ == "__main__":    menu()

    Bei Linux/Mac: Speichere mit Strg+O, Enter, Strg+X

    Bei Windows: Speichere über Datei → Speichern und schließe Notepad

    2. Programm ausführen

    Jetzt kannst du das Programm starten:

    Für alle Betriebssysteme (virtuelle Umgebung muss aktiv sein):

    python blog_verwalten.py
    python blog_verwalten.py

    Mit der Eingabe dieses Befehls braucht es nur ein paar Sekunden bis das Verwaltungsprogramm im Terminal aktiv wird. Du wirst dann gefragt, was du machen willst. Am sinnvollsten ist es, hier jetzt erst einmal Blogs hinzuzufügen (Option 1).

    Wenn du diese Option auswählst, wirst du aufgefordert, die URL des gewünschten Blogs einzugeben, von dem die Inhalte geholt und gespeichert werden sollen.

    Manchmal wirst du die Meldung bekommen, dass Scraping bei diesem Blog nicht erlaubt ist. Das solltest du respektieren.

    Du kannst so viele Blogs einsammeln, wie du möchtest. Ich würde an deiner Stelle erst einmal mit 3-5 Blogs beginnen.

    Insgesamt ist dieser Schritt eher langweilig, weil du nicht siehst, was im Hintergrund passiert. Wenn du neugierig bist, kannst du aber über den Datei-Manager deine angelegte Projektumgebung öffnen. Darin siehst du den Ordner chroma_db mit einer SQLite-Datenbank und einem Ordner mit mehreren Vektoren, was aber für dich alles nicht direkt lesbar und verwendbar ist. Ich fand es trotzdem spannend, mir mal direkt anzuschauen, wie so etwas aussieht.

    Schritt 4: Deinen Chat-Bot gestalten

    Die angelegte Vektor-Datenbank und der eingetragene Mistral-API-Key sind nun die Basis, mit der du deinen Blog-Chatbot erstellst. Grundsätzlich lässt sich dieser sehr unterschiedlich gestalten. Im Bot-Programm, das ich dir im folgenden vorschlage, wirst du beim Start des Chats immer erst gefragt, auf welche Blogs du dich bei deiner Frage beziehen willst. Dann kannst du einen oder mehrere der eingespeicherten Blogs auswählen, dann eine Frage stellen und daraufhin dann eine möglichst hilfreiche Antwort erhalten. Mit dem Befehl ‚quellen‘ erreichst du, dass die Links zu den durchsuchten Beiträgen angezeigt werden. Mit dem Befehl ‚mehr‘ werden nicht nur 3, sondern 10 Beiträge für die Antwort verwendet. (Du kannst diese Zahlen natürlich auch hochsetzen, dann kostet dich das mehr Tokens. Für mich passt es so ganz gut).

    In dem Chatbot-Programm ist auch ein Systemprompt enthalten, den du ebenfalls ändern kannst, wenn du das möchtest. Aber auch hier ist es wahrscheinlich ganz sinnvoll, erst einmal diese Vorlage auszuprobieren. Ich habe eine ganze Weile experimentiert und war dann mit der jetzt entstandenen Version recht zufrieden!

    So gehst du vor, um das Chat-Programm einzutragen:

    Linux/Mac:

    nano chatbot.py
    nano chatbot.py

    Windows:

    notepad chatbot.py
    notepad chatbot.py

    Du trägst diesen Inhalt ein:

    import os
    from dotenv import load_dotenv
    import chromadb
    from chromadb.utils import embedding_functions
    from mistralai import Mistral
    
    # Lade API-Key
    load_dotenv()
    api_key = os.getenv("MISTRAL_API_KEY")
    client_mistral = Mistral(api_key=api_key)
    
    # Lade Vektordatenbank
    client_chroma = chromadb.PersistentClient(path="./chroma_db")
    embedding_fn = embedding_functions.SentenceTransformerEmbeddingFunction(
        model_name="paraphrase-multilingual-MiniLM-L12-v2"
    )
    collection = client_chroma.get_collection(
        name="blog_posts",
        embedding_function=embedding_fn
    )
    
    # Speichere letzte Quellen und Frage
    letzte_quellen = []
    letzte_frage = ""
    
    def hole_verfuegbare_blogs():
        """Zeigt alle gespeicherten Blogs"""
        alle_daten = collection.get()
        if not alle_daten['metadatas']:
            return []
    
        blogs = set(meta['blog_url'] for meta in alle_daten['metadatas'])
        return sorted(list(blogs))
    
    def blog_auswahl():
        """Lässt Nutzer*in Blogs auswählen"""
        blogs = hole_verfuegbare_blogs()
    
        if not blogs:
            print("\n❌ Keine Blogs gespeichert!")
            print("💡 Führe erst 'python blog_verwalten.py' aus.\n")
            return None
    
        print("\n📚 Verfügbare Blogs:")
        print("0 - Alle Blogs durchsuchen")
        for i, blog in enumerate(blogs, 1):
            print(f"{i} - {blog}")
    
        while True:
            wahl = input("\nWelche Blogs durchsuchen? (Zahl oder mehrere mit Komma, z.B. 1,3): ").strip()
    
            if wahl == "0":
                return None  # None = alle Blogs
    
            try:
                nummern = [int(n.strip()) for n in wahl.split(",")]
                ausgewaehlte = [blogs[n-1] for n in nummern if 1 <= n <= len(blogs)]
                if ausgewaehlte:
                    return ausgewaehlte
                else:
                    print("❌ Ungültige Auswahl!")
            except:
                print("❌ Ungültige Eingabe!")
    
    def extrahiere_keywords(frage):
        """Extrahiert wichtige Schlüsselwörter aus der Frage"""
        stopwords = ['was', 'ist', 'sind', 'der', 'die', 'das', 'ein', 'eine', 'mit', 'zu', 'im', 'in',
                     'von', 'für', 'und', 'oder', 'wie', 'wo', 'wann', 'warum', 'welche', 'welcher',
                     'gibt', 'es', 'dazu', 'darüber', 'findest', 'du', 'infos', 'informationen',
                     'schreibt', 'blog', 'beitrag', 'dem', 'den', 'des', 'an', 'auf', 'bei',
                     'nach', 'über', 'aus', 'hier', 'da', 'haben', 'hat', 'wird', 'werden', 'kann',
                     'können', 'soll', 'sollen', 'muss', 'müssen']
    
        woerter = frage.lower().split()
        keywords = [w.strip('?.,!') for w in woerter if w.lower() not in stopwords]
        return keywords
    
    def keyword_suche(keywords, blog_filter=None):
        """Sucht direkt nach Keywords in Titeln und Texten"""
        alle_daten = collection.get()
        treffer = []
    
        for i, meta in enumerate(alle_daten['metadatas']):
            # Blog-Filter anwenden
            if blog_filter and meta['blog_url'] not in blog_filter:
                continue
    
            titel_lower = meta['title'].lower()
            text_lower = alle_daten['documents'][i].lower()
    
            # Zähle Keyword-Matches
            titel_matches = sum(1 for kw in keywords if kw in titel_lower)
            text_matches = sum(1 for kw in keywords if kw in text_lower)
    
            if titel_matches > 0 or text_matches > 1:  # Mind. 1 im Titel ODER 2 im Text
                treffer.append({
                    'id': alle_daten['ids'][i],
                    'doc': alle_daten['documents'][i],
                    'meta': meta,
                    'score': titel_matches * 3 + text_matches
                })
    
        # Nach Score sortieren
        treffer.sort(key=lambda x: x['score'], reverse=True)
        return treffer
    
    def hybrid_suche(frage, blog_filter=None, anzahl_beitraege=3):
        """Kombiniert Keyword-First mit semantischer Suche"""
        # 1. Keywords extrahieren
        keywords = extrahiere_keywords(frage)
    
        # 2. Keyword-Suche
        keyword_treffer = keyword_suche(keywords, blog_filter)
    
        # 3. Semantische Vektorsuche
        if blog_filter:
            vektor_results = collection.query(
                query_texts=[frage],
                n_results=anzahl_beitraege * 2,
                where={"blog_url": {"$in": blog_filter}}
            )
        else:
            vektor_results = collection.query(
                query_texts=[frage],
                n_results=anzahl_beitraege * 2
            )
    
        # 4. Kombiniere: Keyword-Treffer zuerst, dann Vektor-Results
        finale_results = []
        verwendete_ids = set()
    
        # Keyword-Treffer haben Priorität
        for treffer in keyword_treffer[:anzahl_beitraege]:
            finale_results.append({
                'doc': treffer['doc'],
                'meta': treffer['meta'],
                'ist_keyword_match': True
            })
            verwendete_ids.add(treffer['id'])
    
        # Fülle auf mit Vektor-Results
        if vektor_results and vektor_results['documents'][0]:
            for i in range(len(vektor_results['documents'][0])):
                if len(finale_results) >= anzahl_beitraege:
                    break
    
                meta = vektor_results['metadatas'][0][i]
    
                # Prüfe ob schon dabei
                if any(r['meta']['link'] == meta['link'] for r in finale_results):
                    continue
    
                finale_results.append({
                    'doc': vektor_results['documents'][0][i],
                    'meta': meta,
                    'ist_keyword_match': False
                })
    
        if not finale_results:
            return None
    
        return {
            'documents': [[r['doc'] for r in finale_results]],
            'metadatas': [[r['meta'] for r in finale_results]],
            'keyword_flags': [r['ist_keyword_match'] for r in finale_results]
        }
    
    def chat(frage, blog_filter=None, konversation_history=None, anzahl_beitraege=3):
        """Beantwortet Frage basierend auf Blog-Inhalten"""
        global letzte_quellen, letzte_frage
    
        if konversation_history is None:
            konversation_history = []
    
        # Frage speichern
        letzte_frage = frage
    
        # Hybrid-Suche
        results = hybrid_suche(frage, blog_filter, anzahl_beitraege)
    
        if not results or not results['documents'][0]:
            return "❌ Keine passenden Beiträge gefunden!", konversation_history
    
        # Quellen speichern
        letzte_quellen = []
        for i, meta in enumerate(results['metadatas'][0], 1):
            marker = "🎯" if results['keyword_flags'][i-1] else ""
            letzte_quellen.append(f"   {marker}{i}. {meta['title']}\n      {meta['link']}")
    
        # Kontext zusammenbauen
        kontext_teile = []
        for i, doc in enumerate(results['documents'][0], 1):
            meta = results['metadatas'][0][i-1]
            kontext_teile.append(f"[Beitrag {i}: {meta['title']}]\n{doc[:2000]}")
    
        kontext = "\n\n---\n\n".join(kontext_teile)
    
        # System-Prompt
        system_prompt = """Du bist ein hilfreicher Assistent, der auf Basis von Blogbeiträgen antwortet.
    
    REGELN:
    1. Nutze ALLE Informationen aus den gegebenen Texten
    2. Lies die Texte VOLLSTÄNDIG und GENAU
    3. Wenn ein Text die Antwort enthält, NUTZE sie
    4. Antworte natürlich und gesprächig
    5. KEINE Quellenangaben in der Antwort (nur auf explizite Nachfrage)
    6. Wenn du etwas nicht weißt: Sage es ehrlich"""
    
        # Konversationshistorie aufbauen
        messages = [{"role": "system", "content": system_prompt}]
    
        # Bisherige Konversation
        for msg in konversation_history:
            messages.append(msg)
    
        # Aktuelle Frage mit Kontext
        user_message = f"""VERFÜGBARE BLOGBEITRÄGE:
    {kontext}
    
    ---
    
    FRAGE: {frage}"""
    
        messages.append({"role": "user", "content": user_message})
    
        # API-Aufruf
        response = client_mistral.chat.complete(
            model="mistral-small-latest",
            messages=messages,
            temperature=0.3
        )
    
        antwort = response.choices[0].message.content
    
        # Konversation aktualisieren
        konversation_history.append({"role": "user", "content": frage})
        konversation_history.append({"role": "assistant", "content": antwort})
    
        return antwort, konversation_history
    
    def zeige_quellen():
        """Zeigt die durchsuchten Beiträge"""
        global letzte_quellen
    
        if not letzte_quellen:
            print("\n❌ Keine Quellen verfügbar (stelle erst eine Frage).\n")
            return
    
        print("\n📖 Diese Beiträge wurden als relevant erachtet und durchsucht:")
        print("   (🎯 = Keyword-Match im Titel oder Text)\n")
        for quelle in letzte_quellen:
            print(quelle)
        print()
    
    def main():
        global letzte_frage
    
        print("\n" + "=" * 50)
        print("BLOG-CHATBOT")
        print("=" * 50)
    
        # Blog-Auswahl
        blog_filter = blog_auswahl()
    
        if blog_filter is None:
            print("\n🔍 Durchsuche: ALLE Blogs")
        else:
            print(f"\n🔍 Durchsuche: {', '.join(blog_filter)}")
    
        print("\n💬 Stelle deine Fragen!")
        print("\n📋 Befehle:")
        print("   • 'mehr'     → Durchsucht 10 statt 3 Beiträge zur letzten Frage")
        print("   • 'quellen'  → Zeigt die durchsuchten Beiträge")
        print("   • 'wechseln' → Ändert die Blog-Auswahl")
        print("   • 'exit'     → Beendet das Programm\n")
    
        # Konversationshistorie
        konversation = []
    
        # Chat-Loop
        while True:
            eingabe = input("❓ ")
    
            if eingabe.lower() in ['exit', 'quit', 'tschüss', 'bye']:
                print("\nBis bald! 👋\n")
                break
    
            if eingabe.lower() == 'quellen':
                zeige_quellen()
                continue
    
            if eingabe.lower() == 'mehr':
                if not letzte_frage:
                    print("\n❌ Stelle erst eine Frage!\n")
                    continue
                print(f"\n🔎 Durchsuche nun 10 Beiträge zur Frage: '{letzte_frage}'\n")
                antwort, konversation = chat(letzte_frage, blog_filter, konversation, anzahl_beitraege=10)
                print(f"\n💡 {antwort}\n")
                continue
    
            if eingabe.lower() == 'wechseln':
                blog_filter = blog_auswahl()
                konversation = []
                letzte_frage = ""
                if blog_filter is None:
                    print("\n🔍 Durchsuche: ALLE Blogs\n")
                else:
                    print(f"\n🔍 Durchsuche: {', '.join(blog_filter)}\n")
                continue
    
            if not eingabe.strip():
                continue
    
            antwort, konversation = chat(eingabe, blog_filter, konversation, anzahl_beitraege=3)
            print(f"\n💡 {antwort}\n")
    
    if __name__ == "__main__":
        main()
    import osfrom dotenv import load_dotenvimport chromadbfrom chromadb.utils import embedding_functionsfrom mistralai import Mistral# Lade API-Keyload_dotenv()api_key = os.getenv("MISTRAL_API_KEY")client_mistral = Mistral(api_key=api_key)# Lade Vektordatenbankclient_chroma = chromadb.PersistentClient(path="./chroma_db")embedding_fn = embedding_functions.SentenceTransformerEmbeddingFunction(    model_name="paraphrase-multilingual-MiniLM-L12-v2")collection = client_chroma.get_collection(    name="blog_posts",    embedding_function=embedding_fn)# Speichere letzte Quellen und Frageletzte_quellen = []letzte_frage = ""def hole_verfuegbare_blogs():    """Zeigt alle gespeicherten Blogs"""    alle_daten = collection.get()    if not alle_daten['metadatas']:        return []    blogs = set(meta['blog_url'] for meta in alle_daten['metadatas'])    return sorted(list(blogs))def blog_auswahl():    """Lässt Nutzer*in Blogs auswählen"""    blogs = hole_verfuegbare_blogs()    if not blogs:        print("\n❌ Keine Blogs gespeichert!")        print("💡 Führe erst 'python blog_verwalten.py' aus.\n")        return None    print("\n📚 Verfügbare Blogs:")    print("0 - Alle Blogs durchsuchen")    for i, blog in enumerate(blogs, 1):        print(f"{i} - {blog}")    while True:        wahl = input("\nWelche Blogs durchsuchen? (Zahl oder mehrere mit Komma, z.B. 1,3): ").strip()        if wahl == "0":            return None  # None = alle Blogs        try:            nummern = [int(n.strip()) for n in wahl.split(",")]            ausgewaehlte = [blogs[n-1] for n in nummern if 1 <= n <= len(blogs)]            if ausgewaehlte:                return ausgewaehlte            else:                print("❌ Ungültige Auswahl!")        except:            print("❌ Ungültige Eingabe!")def extrahiere_keywords(frage):    """Extrahiert wichtige Schlüsselwörter aus der Frage"""    stopwords = ['was', 'ist', 'sind', 'der', 'die', 'das', 'ein', 'eine', 'mit', 'zu', 'im', 'in',                 'von', 'für', 'und', 'oder', 'wie', 'wo', 'wann', 'warum', 'welche', 'welcher',                 'gibt', 'es', 'dazu', 'darüber', 'findest', 'du', 'infos', 'informationen',                 'schreibt', 'blog', 'beitrag', 'dem', 'den', 'des', 'an', 'auf', 'bei',                 'nach', 'über', 'aus', 'hier', 'da', 'haben', 'hat', 'wird', 'werden', 'kann',                 'können', 'soll', 'sollen', 'muss', 'müssen']    woerter = frage.lower().split()    keywords = [w.strip('?.,!') for w in woerter if w.lower() not in stopwords]    return keywordsdef keyword_suche(keywords, blog_filter=None):    """Sucht direkt nach Keywords in Titeln und Texten"""    alle_daten = collection.get()    treffer = []    for i, meta in enumerate(alle_daten['metadatas']):        # Blog-Filter anwenden        if blog_filter and meta['blog_url'] not in blog_filter:            continue        titel_lower = meta['title'].lower()        text_lower = alle_daten['documents'][i].lower()        # Zähle Keyword-Matches        titel_matches = sum(1 for kw in keywords if kw in titel_lower)        text_matches = sum(1 for kw in keywords if kw in text_lower)        if titel_matches > 0 or text_matches > 1:  # Mind. 1 im Titel ODER 2 im Text            treffer.append({                'id': alle_daten['ids'][i],                'doc': alle_daten['documents'][i],                'meta': meta,                'score': titel_matches * 3 + text_matches            })    # Nach Score sortieren    treffer.sort(key=lambda x: x['score'], reverse=True)    return trefferdef hybrid_suche(frage, blog_filter=None, anzahl_beitraege=3):    """Kombiniert Keyword-First mit semantischer Suche"""    # 1. Keywords extrahieren    keywords = extrahiere_keywords(frage)    # 2. Keyword-Suche    keyword_treffer = keyword_suche(keywords, blog_filter)    # 3. Semantische Vektorsuche    if blog_filter:        vektor_results = collection.query(            query_texts=[frage],            n_results=anzahl_beitraege * 2,            where={"blog_url": {"$in": blog_filter}}        )    else:        vektor_results = collection.query(            query_texts=[frage],            n_results=anzahl_beitraege * 2        )    # 4. Kombiniere: Keyword-Treffer zuerst, dann Vektor-Results    finale_results = []    verwendete_ids = set()    # Keyword-Treffer haben Priorität    for treffer in keyword_treffer[:anzahl_beitraege]:        finale_results.append({            'doc': treffer['doc'],            'meta': treffer['meta'],            'ist_keyword_match': True        })        verwendete_ids.add(treffer['id'])    # Fülle auf mit Vektor-Results    if vektor_results and vektor_results['documents'][0]:        for i in range(len(vektor_results['documents'][0])):            if len(finale_results) >= anzahl_beitraege:                break            meta = vektor_results['metadatas'][0][i]            # Prüfe ob schon dabei            if any(r['meta']['link'] == meta['link'] for r in finale_results):                continue            finale_results.append({                'doc': vektor_results['documents'][0][i],                'meta': meta,                'ist_keyword_match': False            })    if not finale_results:        return None    return {        'documents': [[r['doc'] for r in finale_results]],        'metadatas': [[r['meta'] for r in finale_results]],        'keyword_flags': [r['ist_keyword_match'] for r in finale_results]    }def chat(frage, blog_filter=None, konversation_history=None, anzahl_beitraege=3):    """Beantwortet Frage basierend auf Blog-Inhalten"""    global letzte_quellen, letzte_frage    if konversation_history is None:        konversation_history = []    # Frage speichern    letzte_frage = frage    # Hybrid-Suche    results = hybrid_suche(frage, blog_filter, anzahl_beitraege)    if not results or not results['documents'][0]:        return "❌ Keine passenden Beiträge gefunden!", konversation_history    # Quellen speichern    letzte_quellen = []    for i, meta in enumerate(results['metadatas'][0], 1):        marker = "🎯" if results['keyword_flags'][i-1] else ""        letzte_quellen.append(f"   {marker}{i}. {meta['title']}\n      {meta['link']}")    # Kontext zusammenbauen    kontext_teile = []    for i, doc in enumerate(results['documents'][0], 1):        meta = results['metadatas'][0][i-1]        kontext_teile.append(f"[Beitrag {i}: {meta['title']}]\n{doc[:2000]}")    kontext = "\n\n---\n\n".join(kontext_teile)    # System-Prompt    system_prompt = """Du bist ein hilfreicher Assistent, der auf Basis von Blogbeiträgen antwortet.REGELN:1. Nutze ALLE Informationen aus den gegebenen Texten2. Lies die Texte VOLLSTÄNDIG und GENAU3. Wenn ein Text die Antwort enthält, NUTZE sie4. Antworte natürlich und gesprächig5. KEINE Quellenangaben in der Antwort (nur auf explizite Nachfrage)6. Wenn du etwas nicht weißt: Sage es ehrlich"""    # Konversationshistorie aufbauen    messages = [{"role": "system", "content": system_prompt}]    # Bisherige Konversation    for msg in konversation_history:        messages.append(msg)    # Aktuelle Frage mit Kontext    user_message = f"""VERFÜGBARE BLOGBEITRÄGE:{kontext}---FRAGE: {frage}"""    messages.append({"role": "user", "content": user_message})    # API-Aufruf    response = client_mistral.chat.complete(        model="mistral-small-latest",        messages=messages,        temperature=0.3    )    antwort = response.choices[0].message.content    # Konversation aktualisieren    konversation_history.append({"role": "user", "content": frage})    konversation_history.append({"role": "assistant", "content": antwort})    return antwort, konversation_historydef zeige_quellen():    """Zeigt die durchsuchten Beiträge"""    global letzte_quellen    if not letzte_quellen:        print("\n❌ Keine Quellen verfügbar (stelle erst eine Frage).\n")        return    print("\n📖 Diese Beiträge wurden als relevant erachtet und durchsucht:")    print("   (🎯 = Keyword-Match im Titel oder Text)\n")    for quelle in letzte_quellen:        print(quelle)    print()def main():    global letzte_frage    print("\n" + "=" * 50)    print("BLOG-CHATBOT")    print("=" * 50)    # Blog-Auswahl    blog_filter = blog_auswahl()    if blog_filter is None:        print("\n🔍 Durchsuche: ALLE Blogs")    else:        print(f"\n🔍 Durchsuche: {', '.join(blog_filter)}")    print("\n💬 Stelle deine Fragen!")    print("\n📋 Befehle:")    print("   • 'mehr'     → Durchsucht 10 statt 3 Beiträge zur letzten Frage")    print("   • 'quellen'  → Zeigt die durchsuchten Beiträge")    print("   • 'wechseln' → Ändert die Blog-Auswahl")    print("   • 'exit'     → Beendet das Programm\n")    # Konversationshistorie    konversation = []    # Chat-Loop    while True:        eingabe = input("")        if eingabe.lower() in ['exit', 'quit', 'tschüss', 'bye']:            print("\nBis bald! 👋\n")            break        if eingabe.lower() == 'quellen':            zeige_quellen()            continue        if eingabe.lower() == 'mehr':            if not letzte_frage:                print("\n❌ Stelle erst eine Frage!\n")                continue            print(f"\n🔎 Durchsuche nun 10 Beiträge zur Frage: '{letzte_frage}'\n")            antwort, konversation = chat(letzte_frage, blog_filter, konversation, anzahl_beitraege=10)            print(f"\n💡 {antwort}\n")            continue        if eingabe.lower() == 'wechseln':            blog_filter = blog_auswahl()            konversation = []            letzte_frage = ""            if blog_filter is None:                print("\n🔍 Durchsuche: ALLE Blogs\n")            else:                print(f"\n🔍 Durchsuche: {', '.join(blog_filter)}\n")            continue        if not eingabe.strip():            continue        antwort, konversation = chat(eingabe, blog_filter, konversation, anzahl_beitraege=3)        print(f"\n💡 {antwort}\n")if __name__ == "__main__":    main()

    Bei Linux/Mac: Speichere mit Strg+O, Enter, Strg+X

    Bei Windows: Speichere über Datei → Speichern und schließe Notepad

    Damit hast du es geschafft und kannst deinen Chatbot jetzt nutzen.

    Schritt 5: Deinen Chatbot nutzen!

    Mit diesem Befehl startest du deinen Chatbot:

    Für alle Betriebssysteme (virtuelle Umgebung muss aktiv sein):

    python chatbot.py
    python chatbot.py

    Es braucht wahrscheinlich ein paar Sekunden. Wie oben beschrieben stellt der Chatbot dir dann in der oben geteilten Version des Bot-Programms zunächst die Frage, welche eingespeicherten Blogs du als Basis nutzen willst. Dann kannst du deine Frage eingeben. Wenn du noch tiefer recherchieren willst, dann gib mehr ein. Wenn du andere Blogs als Grundlage nehmen willst, dann nutze den Befehl wechseln. Mit quellen siehst du, welche Beiträge der Bot durchsucht hat.

    Hier ist ein exemplarischer Chatverlauf, bei dem ich den Bot auf die eBildungslabor-Beiträge als RAG fokussiert habe:

    ❓ Wie definiert Nele Kreativität?

    💡 Nele definiert Kreativität im pädagogischen Kontext als die Fähigkeit, Neues denken zu können. Dabei geht es nicht primär um künstlerisches Tätigsein, sondern darum, über das Bestehende hinauszudenken und innovative Lösungen zu finden. Diese Definition steht im Rahmen der 4K-Kompetenzen, die auch Kommunikation, Kollaboration und kritisches Denken umfassen. Kreativität wird hier also als eine Schlüsselkompetenz für den digitalen Wandel und die aktive Gestaltung unserer Gesellschaft verstanden.

    ❓ Was schreibt Nele zu H5P?

    💡 Nele schreibt über H5P, dass es ein großartiges und offenes Tool zur Gestaltung von interaktiven Online-Materialien zum Lernen und Lehren ist. Sie schätzt besonders, dass es immer wieder neue Inhaltstypen gibt, die viel Raum für eine gezielte Nutzung im jeweiligen pädagogischen Setting bieten. Nele erwähnt, dass viele ihrer Lieblings-Inhaltstypen von Oliver, einem freiberuflichen Programmierer für H5P, entwickelt wurden.

    Sie stellt verschiedene Anwendungen und Möglichkeiten von H5P vor, wie den Phrase-Randomizer, der für kreative Ideenentwicklung genutzt werden kann, oder die Game Map, mit der interaktive Karten gestaltet werden können. Nele beschreibt auch, wie sie H5P genutzt hat, um aus Fotokollen interaktive Lerninhalte zu erstellen, indem sie den Inhaltstyp „Image Hotspots“ verwendet hat. Dabei werden Hintergrundbilder mit zusätzlichen Informationen und Erläuterungen versehen, um so einen vertiefenden Lerninhalt zu schaffen.

    Insgesamt zeigt Nele auf, wie vielseitig und nützlich H5P für die Gestaltung interaktiver und kreativer Bildungsmaterialien sein kann.

    ❓ quellen

    📖 Diese Beiträge wurden als relevant erachtet und durchsucht:
    (🎯 = Keyword-Match im Titel oder Text)

    🎯1. Praxis-Tipp: Inspirationsduschen mit H5P
    ebildungslabor.de/blog/praxis-
    🎯2. H5P-Hacking: Mit der Game Map interaktive Online-Karten gestalten
    ebildungslabor.de/blog/h5p-hac
    🎯3. Schnelle Idee für H5P: Image Hotspots statt ‚Fotokoll‘
    ebildungslabor.de/blog/schnell

    Ich finde: Ziemlich gut und nützlich!

    Mit exit kommst du aus dem Bot wieder raus und kannst dich dann daran machen, z.B. die Bot-Datei zu überarbeiten. (Du weißt ja jetzt, wie es geht: nano chatbot.py (Linux/Mac) bzw. notepad chatbot.py (Windows) eingeben und Änderungen vornehmen.)

    Wenn du das Terminal geschlossen hast und irgendwann später den Bot wieder öffnen willst, dann öffnest du wie in Schritt 2 beschrieben mit dem cd Befehl wieder das Verzeichnis, aktivierst anschließend die virtuelle Umgebung und startest dann das Botprogramm (mit dem Befehl: python chatbot.py)

    Fazit

    Ich habe mir erste Blogs eingespeichert und mit dem entwickelten Bot eine Weile gechattet. Komplexere Anfragen (Wie definiert Melanie im Vergleich zu Nele den Begriff Kreativität?) sind mit diesem Basis-Setup nicht möglich. Um sich aber einen Überblick über Blog-Inhalte zu verschaffen und zusammenfassende Verbindungen zu nutzen sowie Hinweise auf weiterführende Quellen zu erhalten, finde ich diese selbst gebastelte Anwendung richtig hilfreich. Ich kann dir das Nachbasteln somit sehr empfehlen.

    Viel Freude beim Erkunden und Ausprobieren!

    Bonus: Einen RAG-Chatbot online bringen!

    So wie du einen RAG-Chatbot in deinem Terminal gestalten kannst, kannst du solch eine Anwendung natürlich auch auf einen Online-Server übertragen und dann anderen öffentlich zur Verfügung stellen. Das wird im Internet ja zuhauf angeboten. Man kann es sich eben aber auch selbst gestalten.

    Ich habe das mit einer leicht angepassten Version des obigen Bot-Programms ausprobiert, in dem ich darin nur die Inhalte von meiner eigenen Website eingespeist habe und dazu einen Bot erstellt habe. Der Server kostet ca. 4 Euro / Monat. Ich lasse ihn auf eine Subdomain meiner Website verweisen. Ich habe außerdem (um meine Mistral-Tokens nicht alle direkt aufzubrauchen) eine Begrenzung auf 25 Fragen bei der öffentlichen Nutzung eingestellt. Als Interface habe ich die Open Source Software Streamlit genutzt (anstelle des Terminals auf dem jeweils eigenen Rechner). Das Ergebnis kannst du auf bot.ebildungslabor.de ausprobieren.

    (Wenn wir mit einer lokalen und damit dezentralen Nutzung vorankommen, so wie ich es in meinem obigen Blogbeitrag beschrieben habe, dann sind solche Website-Bots bald überflüssig. Schließlich ist es ja viel sinnvoller, sich selbst genau die Anwendung mit den Inhalten, Einstellungen und Systemprompts zu bauen, die man gerade braucht!)

    #DigitaleMündigkeit #KünstlicheIntelligenzKI