{"id":27939,"date":"2025-09-11T14:16:51","date_gmt":"2025-09-11T12:16:51","guid":{"rendered":"https:\/\/blog.mi.hdm-stuttgart.de\/?p=27939"},"modified":"2025-09-11T14:16:52","modified_gmt":"2025-09-11T12:16:52","slug":"entwickeln-eines-ki-tools-zum-generieren-von-strukturierten-lerninhalten","status":"publish","type":"post","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2025\/09\/11\/entwickeln-eines-ki-tools-zum-generieren-von-strukturierten-lerninhalten\/","title":{"rendered":"Entwickeln eines KI-Tools zum Generieren von strukturierten Lerninhalten"},"content":{"rendered":"\n<p>F\u00fcr den Kurs &#8220;Software Development for Cloud Computing&#8221; wollte ich eine Anwendung entwickeln, mit der konkrete Aufgaben f\u00fcr ein gegebenes Lernziel generiert werden k\u00f6nnen. Der Nutzer stellt dabei Informationen zum Lernziel, sowie seines aktuellen Niveaus und der geplanten Lerndauer zur Verf\u00fcgung. Auf dieser Basis k\u00f6nnen dann die konkreten Aufgaben, die zum Erreichen des Ziels n\u00f6tig sind, generiert werden. Die Aufgaben bauen dabei auf einander auf, sodass der Nutzer von Tag zu Tag seine F\u00e4higkeiten steigern kann. Des weiteren werden aktuelle Studien beim Generieren ber\u00fccksichtigt. Die Aufgaben sollen in einem Frontend angesehen und als erledigt markiert werden k\u00f6nnen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Mein Wissensstand &#8211; Der Status Quo<\/h2>\n\n\n\n<p>Ich hatte zuvor noch nie mit AWS oder anderen Cloudtechnologien gearbeitet und sah darin ein Thema mit gro\u00dfem Lernpotential f\u00fcr das Projekt. Des weiteren hatte ich keine Erfahrungen in der Cross-Platform-Entwicklung von Anwendungen, auch in diesem Bereich wollte ich mich durch das Projekt weiterentwickeln.<br>Im Entwickeln von Anwendungen mit KI-Integration hatte ich bereits ein paar Erfahrungen gesammelt, da ich in meinem Praxissemester an einer KI-gest\u00fctzten Anwendung zur Prozessoptimierung mitgearbeitet hatte. Hier bekam ich Einblicke in die Verwendung von Frameworks zur Implementierung von KI-Agentensystemen.<\/p>\n\n\n\n<p>Ein Faktor, der sich als eine m\u00f6gliche Schwierigkeit in meinem Projekt abzeichnete, war die Teamgr\u00f6\u00dfe. Ich hatte vor, das Projekt alleine durchzuf\u00fchren, da ich mir auch hiervon einige n\u00fctzliche Erfahrungen versprach.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Der Weg zum Zielprojekt &#8211; Herausforderungen und Learnings<\/h2>\n\n\n\n<p>Ich begann die Arbeit an dem Projekt mit organisatorischen \u00dcberlegungen. Da ich alleine war, wollte ich den Umfang des Projektes nicht sprengen und die geplanten Funktionen zun\u00e4chst auf ein n\u00f6tiges Minimum reduzieren. Hierbei entschied ich mich dazu, dass die App folgende Features umfassen sollte:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Anforderungen an die zu lernende T\u00e4tigkeit sollen eingegeben werden k\u00f6nnen<\/li>\n\n\n\n<li>KI-gest\u00fctzt sollen konkrete Aufgaben generiert werden, die der Nutzer ausf\u00fchren soll, um etwas zu erlernen<\/li>\n\n\n\n<li>Diese konkreten Aufgaben werden dann in der App angezeigt und k\u00f6nnen dort abgeschlossen werden<\/li>\n<\/ul>\n\n\n\n<p>Dies war der f\u00fcr mich logisch erscheindende minimale Umfang f\u00fcr eine funktionale, aber nicht \u00fcberm\u00e4\u00dfig aufw\u00e4ndig zu entwickelnde Anwendung. Sp\u00e4ter sollte sich der Aufwand allerdings dennoch als ziemlich gro\u00df herausstellen.<br>Den n\u00e4chste Schritt des Projektes stellte die <strong>Technologieauswahl <\/strong>dar:<\/p>\n\n\n\n<p>Die Auswahl der Spache f\u00fcr die Entwicklung des Backends erschien mir einfach: Python bot nach meinem Wissensstand den besten Support f\u00fcr Frameworks, mit denen sich LLMs (&#8220;Large Language Models&#8221;) in Code integrieren lassen und damit das Entwickeln von KI-gest\u00fctzten Anwendungen erm\u00f6glichen. Eine andere Sprache zog ich nicht in Betracht, zumal die KI-Agentenframeworks, die ich w\u00e4hrend meines Praktikums verwendete, ebenfalls Python-Frameworks waren. Die Vorteile von Python in diesem Zusammenhang w\u00fcrde ich vor allem mit der gro\u00dfen Anzahl an Libraries, die das Entwickeln mit LLM-APIs erm\u00f6glichen, sowie die breite Unterst\u00fctzung in Cloud-Umgebungen zusammenfassen. Ein m\u00f6glicher Nachteil k\u00f6nnten Performanceprobleme, besonders im Fall einer m\u00f6glichen Skalierung der Anwendung sein. Dies stellte f\u00fcr mich im Rahmen des Uniprojekts jedoch kein gravierendes Problem dar.<br>F\u00fcr das Frontend, das in Form einer App im Cross-Plattform-Stil umgesetzt werden sollte, entschied ich mich zun\u00e4chst f\u00fcr Flutter. Ich las in diesem Zusammenhang von der hohen Performance und der wachsenden Community und setzte ein lokales Flutter-Projekt auf. Der Beginn war jedoch mit einer Einarbeitung verbunden, da Flutter auf Dart, einer mir zu diesem Zeitpunkt unbekannten Programmiersprache basierte. Nachdem ich die Idee meines Projekts zum ersten Mal vorgestellt hatte, enschied ich mich aufgrund des holprigen Startes dazu, die Auswahl der Frontend-Technologie noch einmal zu \u00fcberdenken. In diesem Zuge stie\u00df ich auf React Native, das mir als das etabliertere, ausgereiftere Framework erschien. Des weiteren hatte ich in der Vergangenheit bereits Erfahrung mit React sammeln k\u00f6nnen, was den gr\u00f6\u00dften Vorteil f\u00fcr mich darstellte, da ich dadurch den Fokus des Projektes auf das Wesentliche, f\u00fcr mich vor allem das Verst\u00e4ndnis des AWS-Universums, lenken konnte.<br>Zur Auswahl einer LLM-API, die meine Anwendung intelligent machen und das Generieren der Aufgaben erm\u00f6glichen sollte, verglich ich mehrere Anbieter. Ich enschied mich schlie\u00dflich f\u00fcr die &#8220;Gemini-2.5-Flash&#8221;-API, da diese eine leistungsstarke aber dennoch kostenlose L\u00f6sung darstellte. Dies funktioniert unter der Bedingung der Datennutzung zum Training neuer Modelle, was zu Problemen hinsichtlich der Privatsph\u00e4re f\u00fchren k\u00f6nnte. Im Rahmen meines Projekts war dies jedoch erneut ein Kompromiss, den ich eingehen konnte und musste, um Kosten zu vermeiden.<br>Die letzte Enscheidung war bez\u00fcglich des Deployments zu treffen. Ich entschied mich f\u00fcr das Deployment des Backend-Codes in einer AWS Lambda, da die geplante Funktionsweise des Backends gut zu meinem Verst\u00e4ndnis von AWS Lambda passt. Eine Lambda ist ein ereignisgesteuerter Serverless-Dienst. Der Code meines Python-Backends wird also nur im Bedarfsfall, also bei einem API-Call, gestartet. Dadurch muss kein Server konstant aktiviert sein, durch Pay-per-Use k\u00f6nnen Kosten gespart werden. Die Aufgaben werden, durch Einbeziehen der externen LLM-API, generiert und nach dem Fertigstellen an den Client zur\u00fcckgegeben. Zu diesem Zeitpunkt kann die Lambda wieder heruntergefahren werden. Diese asynchrone Kommunikation sollte mich sp\u00e4ter vor weitere Herausforderungen stellen (siehe unten). <\/p>\n\n\n\n<p>Ein Learning aus Projekten der Vergangenheit war, dass sich durch detaillierte Plaung einige Probleme im Vorhinein verhindern lassen. So entschied ich mich, in diesem Projekt relativ viel Zeit in die Ausarbeitung der Projektidee im Vorhinein zu investieren, um sp\u00e4ter in einen fl\u00fcssigeren Entwicklungsprozess kommen zu k\u00f6nnen.<br>Zuerst entwickelte ich Wireframes der App. Ich recherchierte nach Alternativen zu Figma, da mich hier die Begrenzug der Anzahl an m\u00f6glichen Projekten sowie die, nach meinem Gef\u00fchl starke Funktionslimitierung in der kostenlosen Version st\u00f6rte. Ich stie\u00df auf Penpot, ein OpenSource-Tool, das ohne Einschr\u00e4nkungen auskam und mir geeignet erschien. Es verf\u00fcgt \u00fcber die M\u00f6glichkeit des Exports von CSS-Code, was den Designprozess beschleunigen kann und was bei Figma in der kostenlosen Version nicht m\u00f6glich ist. <br>Ich erstellte Wireframes f\u00fcr eine Startseite sowie ein Popup-Fenster, das dem Generieren weiterer Aufgaben dienen sollte. Ich verwendete dabei ein minimalistisches Design, um auch in diesem Sinne dem Ziel, lediglich einen MVP zu implementieren, treu zu bleiben.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik.png\"><img loading=\"lazy\" decoding=\"async\" width=\"754\" height=\"857\" data-attachment-id=\"27953\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2025\/09\/11\/entwickeln-eines-ki-tools-zum-generieren-von-strukturierten-lerninhalten\/grafik-13\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik.png\" data-orig-size=\"754,857\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"grafik\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik.png\" alt=\"\" class=\"wp-image-27953\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik.png 754w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-264x300.png 264w\" sizes=\"auto, (max-width: 754px) 100vw, 754px\" \/><\/a><figcaption class=\"wp-element-caption\">Minimalistisches Wireframe des Homescreens und des Popups in Penpot<\/figcaption><\/figure>\n\n\n\n<p>Als n\u00e4chstes machte ich mir Gedanken zum Ablauf der LLM-Anfragen. Es sollten nicht direkt alle Angaben des Nutzers an das Modell gegeben werden, sondern stattdessen zuerst Informationen zur aktuellen Studienlage etc. generiert werden, die dann die Qualit\u00e4t der finalen Ausgaben des LLMs erh\u00f6hen sollten. Im Folgenden ist der Ablauf detailliert dargestellt:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"536\" data-attachment-id=\"27956\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2025\/09\/11\/entwickeln-eines-ki-tools-zum-generieren-von-strukturierten-lerninhalten\/grafik-15\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-2.png\" data-orig-size=\"2724,1426\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"grafik\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-2-1024x536.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-2-1024x536.png\" alt=\"\" class=\"wp-image-27956\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-2-1024x536.png 1024w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-2-300x157.png 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-2-768x402.png 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-2-1536x804.png 1536w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-2-2048x1072.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Darstellung des Ablaufs der LLM-Aufrufe und des Datenflusses<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Agentenframework: Google ADK<\/h3>\n\n\n\n<p>Als die inhaltlichen \u00dcberlegungen zum LLM-Ablauf gemacht waren, musste ich mich noch f\u00fcr ein Framework entscheiden, mit dem ich diesen Ablauf umsetzen w\u00fcrde. Ich entschied mich nach einiger Recherche f\u00fcr Google ADK. Zuvor hatte ich noch nicht mit diesem Framework gearbeitet, aber es erschien mir vielversprechend, bot umfangreiche M\u00f6glichkeiten zur Umsetzung verschiedener Hierarchien und hatte generell einen passenden Funktionsumfang. Es war f\u00fcr mich eher ein Vorteil, dass ich noch nicht mit dem Framework gearbeitet hatte, da ich meine F\u00e4higkeiten in diesem Bereich gerne erweitern wollte. In der Vergangenheit hatte ich bereits mit LangGraph, DSPy, CrewAI und OpenAI Swarm gearbeitet und wollte diese Liste gerne erweitern. <br>In Google ADK legte ich die oben dargestellten Schritte jeweils als einzelne Agenten an, deren Ausgaben dann in die Instruktionen der folgenden Agenten \u00fcbergeben wurden. Dies wird via des Attributs &#8220;output_key&#8221; ermg\u00f6licht. Der angegebene output_key kann dann in die Instruktion des folgenden Agenten integriert werden, wodurch auf die Ausgaben des vorherigen Agenten referneziert wird.<br>Der Agent &#8220;Step_3&#8221; generiert die finale Ausgabe in einem eigens spezifizierten Schema. Die Definition der Agenten sieht folgenderma\u00dfen aus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">\nfrom google.adk.agents import Agent\n\nfrom agentic_sys.models import FinalTaskOutputList\nfrom utils import load_instructions\nfrom google.adk.agents import SequentialAgent\n\nstep1_agent = Agent(\n    name=&quot;Step_1&quot;,\n    model=&quot;gemini-2.5-flash&quot;,\n    description=&quot;Dieser Agent recherchiert, wie man auf Basis der Studienlage am besten lernt.&quot;,\n    instruction=load_instructions(1),\n    include_contents=&#039;none&#039;,\n    output_key=&quot;general_study&quot;\n)\n<\/code><\/pre>\n\n\n\n<p>Die Agenten sollten nach einander ausge\u00fchrt werden, was in Google ADK durch den &#8220;Sequence Agent&#8221; erm\u00f6glicht wird:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">from google.adk.agents import SequentialAgent\nfrom agentic_sys.agent import step1_agent, step2_agent, step3_agent\n\nsequence_agent = SequentialAgent(\n    name=&quot;Sequence_Agent&quot;,\n    description=&quot;Executes all steps sequentally.&quot;,\n    sub_agents=&#091;step1_agent, step2_agent, step3_agent]\n)\n\nroot_agent = sequence_agent<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Entwicklung der App<\/h3>\n\n\n\n<p>Ich startete den eigentlichen Entwicklungsprozess meiner App mit der Einarbeitung in Flutter. Ich las mich in die Dokumentation ein, merkte jedoch relativ schnell, dass ich nicht auf Anhieb warm damit wurde und entschied mich dann aus besagten Gr\u00fcnden zu einem Wechsel zu React Native. Ich setzte ein neues Projekt mit React Native in Expo, einem Framework, das das Entwickeln, Testen und Deployen von React Native Apps vereinfacht, und erarbeitete mir die Grundlagen des Frameworks. Ich hatte jedoch von Anfang an einige Probleme und musste viel Arbeit leisten, um die ersten Komponenten tats\u00e4chlich auf dem Bildschirm zu sehen. Die gewissen Eigenheiten, die Expo mit sich brachte, musste ich erst einmal verstehen. So waren z.B. nicht alle Funktionen des &#8220;reinen&#8221; React Native mit Expo kompatibel, was ich zuerst erkennen und anpassen musste. Ein Vorteil des Frameworks war, dass ich die Komponenten per Expo-App auf meinem Smartphone anzeigen lassen konnte, was ein (meist) komfortables Testerlebnis erm\u00f6glichte.<br>Ich erstellte die Komponente des Homescreens und des Popups zum Generieren weiterer Aufgaben. F\u00fcr das Styling verwendete ich Nativewind, das praktischer zu handhaben, schneller zu schreiben und \u00fcbersichtlicher ist als normales CSS per Stylesheet. Zudem verwendet NativeWind die bekannten Tailwind CSS-Klassen, was mit einer gro\u00dfen Community einhergeht. NativeWind funktioniert plattform\u00fcbergreifend und hat einen geringen Runtime-Overload.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Deployment in AWS<\/h3>\n\n\n\n<p>Ich Entschied aufgrund des Aufwands vorerst auf ein automatisiertes Deployment via Terraform zu verzichten. AWS bietet ein manuelles Deployment der Python-Files via Zip-Upload in die AWS Lambda an, was ich nutzen wollte. Dazu musste ich zun\u00e4chst die Dateien samt aller Dependencies in eine passende Form bringen: Alle .py-Dateien mussten auf der gleichen Ebene liegen. Hier stie\u00df ich auf mein erstes gr\u00f6\u00dferes Problem. Die Gr\u00f6\u00dfe der Zip, die hochgeladen werden kann, ist auf 250MB begrenzt. Die Dependency &#8220;Google ADK&#8221; \u00fcbersteigt diese Gr\u00f6\u00dfe bei weitem, was dazu f\u00fchrte, dass ein Upload nicht m\u00f6glich war. Mit diesem Problem hatte ich nicht gerechnet, generell war mir nicht bewusst gewesen, dass Dependencygr\u00f6\u00dfen zu Problemen bei Deployments f\u00fchren k\u00f6nnen. Meine Alternativen waren folgende: <br>Entweder w\u00fcrde ich vom Gedanken der Serverless-Function weggehen und stattdessen in AWS Fargate, einem Serverless-Container-Dienst deployen. Dies w\u00fcrde jedoch mit langsameren Startzeiten einhergehen. Au\u00dferdem w\u00fcrde nach meinem Verst\u00e4ndnis der gro\u00dfe Vorteil von AWS Lambda in meinem Anwendungsfall, dass sich die Lambda automatisch beendet wenn die Generierung der Aufgaben abgeschlossen ist, verloren gehen. <br>Die zweite L\u00f6sung des Problems best\u00fcnde darin, das Agentenframework &#8220;Google ADK&#8221; durch ein anderes, kleineres zu ersetzen, was jedoch eine erneute Programmierung des Agentensystems n\u00f6tig machen w\u00fcrde. Ich entschied mich dennoch f\u00fcr diese Variante, da ich AWS Lambda f\u00fcr eine gute L\u00f6sung hielt und den Aufwand f\u00fcr die Anpassung f\u00fcr machbar hielt. Ich w\u00e4hlte LangGraph als alternatives Framework aus, die Gr\u00f6\u00dfe betrug deutlich unter 100MB, was ein problemloses Deployment erm\u00f6glichen w\u00fcrde. Da ich bereits Erfahrungen in LangGraph gesammelt hatte, gelang mir das Erstellen des neuen KI-Systems relativ schnell. Das Deployment funktionierte, nachdem ich die Python Version der Lambda mit der Version des hochgeladenen Codes abglich.<\/p>\n\n\n\n<p>Die n\u00e4chste Entscheidung, die ich treffen musste, war das Speichern der Umgebungsvariablen in AWS. Dies betraf vor allem den API-Key zur externen Google-Gemini-API. Ich entschied mich dazu, die Variable als Secure String im AWS Systems Manager Parameter Store zu speichern. Eine Speicherung in einer Lambda-Umgebungsvariablen ist mit Sicherheitsrisiken verbunden. Eine Speicherung im AWS Secrets Manager ist mit Kosten verbunden, was f\u00fcr mich auch nicht in Frage kam.<\/p>\n\n\n\n<p>Damit einher ging die n\u00e4chste Herausforderung, die ich auch sp\u00e4ter beim Anbinden an das API-Gateway und andere Services erneut aufkommen sollte: Ich musste Berechtigungen vergeben, um den Zugriff auf Ressourcen \u00fcber unterschiedliche AWS Services hinweg zu erm\u00f6glichen. Hier halfen mir Tutorials herauszufinden, welche Berechtigungen f\u00fcr meinen Anwendungsfall n\u00f6tig war zu erteilen. Fogende Eintr\u00e4ge erm\u00f6glichten beispielsweise den Zugriff aus der Lambda auf die Umgebungsvariablen, die im Parameter Store gespeichert sind:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">{\n\t&quot;Version&quot;: &quot;2012-10-17&quot;,\n\t&quot;Statement&quot;: &#091;\n\t\t{\n\t\t\t&quot;Sid&quot;: &quot;VisualEditor0&quot;,\n\t\t\t&quot;Effect&quot;: &quot;Allow&quot;,\n\t\t\t&quot;Action&quot;: &#091;\n\t\t\t\t&quot;ssm:GetParametersByPath&quot;,\n\t\t\t\t&quot;ssm:GetParameter&quot;\n\t\t\t],\n\t\t\t&quot;Resource&quot;: &quot;arn:aws:ssm:eu-central-1:xxxx:parameter\/skillstruct\/google_ai&quot;\n\t\t}\n\t]\n}<\/code><\/pre>\n\n\n\n<p>Des weiteren musste ich den Code so anpassen, dass er \u00fcber ein API-Gateway aufgerufen werden kann. Das Erstellen eines API-Gateways war erneut mit dem Erteilen von Berechtigungen verbunden. Auf die per API gesendeten Inhalte konnte ich \u00fcber ein Event-Objekt zugreifen, das an den Code der Lambda \u00fcbergeben wird. <\/p>\n\n\n\n<p>Ein weiteres Problem war, dass das Generieren der Aufgaben via LLM relativ lang dauerte und die maximale Lauzeit der Lambda \u00fcberschritt. Es kam zu einem Timeout. Die L\u00f6sung des Problems war jedoch ziemlich simpel: Ich musste lediglich den Schwellenwert im AWS Dashboard erh\u00f6hen, der festlegt, nach wie vielen Sekunden sich die Lambda durch einen Timeout beenden sollte.<\/p>\n\n\n\n<p>Das letzte gr\u00f6\u00dfere Problem war Folgendes: Das API-Gateway wartet maximal 29 Sekunden auf die Generierung der Antwort durch die Lambda. Durch die Anbindung an das LLM dauerte die Generierung der Antowort jedoch l\u00e4nger. Um dieses Problem zu umgehen, musste ich meine AWS Architektur umbauen. Ich f\u00fcgte eine zweite Lambda hinzu, die mit dem API-Gateway verbunden ist und die API-Anfragen des Clients samt der zum Generieren notwendigen Informationen entgegennimmt. Die Lambda legt einen neuen Job, bestehend aus einer Job-ID und den Informationen des Clients, an und gibt ihn in den AWS Simple Queue Service (SQS). Ich entschied mich f\u00fcr AWS SQS \u00fcber Alternativen wie z.B. RabbitMQ, da es nativ in AWS integriert ist und optimal mit AWS Lambda etc. funktioniert. Es war keine tiefe Einarbeitung n\u00f6tig und war schnell einsatzbereit.<br>Die Job-ID wird an den Client zur\u00fcckgegeben. Die urspr\u00fcngliche Lambda wurde zur Worker-Lambda umfuntioniert und nun durch einen neuen Task in der SQS getriggert. Die Aufgaben werden wie zuvor generiert, nach Abschluss jedoch in einer DynamoDB gespeichert. Ich entschied mich f\u00fcr DynamoDB \u00fcber Alternativen wie Amazon RDS, da DynamoDB sehr &#8220;serverless-freundlich&#8221; mit nativer Anbindung an Lambda ist. Es war die f\u00fcr mich naheliegendste Wahl, ohne gro\u00dfe Einarbeitungsaufw\u00e4nde. Die generierten Aufgaben k\u00f6nnen dann per Job-ID referenziert werden.<br>Der Client pollt, nachdem er die Job-ID als Anwort auf seine Anfrage erhalten hat, mit \u00dcbergabe dieser an die Lambda auf eine generierte Antwort. Wenn die Job-ID bei der Anfrage gesetzt ist, wird kein neuer Job angelegt sondern stattdessen in der DynamoDB abgefragt, ob der Job bereits abgeschlossen ist. In dem Fall werden die Aufgaben an den Client zur\u00fcckgegeben. <br>Im Folgenden ist eine \u00dcbersicht der Architektur dargestellt:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-3.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"551\" data-attachment-id=\"27978\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2025\/09\/11\/entwickeln-eines-ki-tools-zum-generieren-von-strukturierten-lerninhalten\/grafik-16\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-3.png\" data-orig-size=\"2754,1483\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"grafik\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-3-1024x551.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-3-1024x551.png\" alt=\"\" class=\"wp-image-27978\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-3-1024x551.png 1024w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-3-300x162.png 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-3-768x414.png 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-3-1536x827.png 1536w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/grafik-3-2048x1103.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>Ein Problem, das bis zuletzt ohne zufriedenstellende L\u00f6sung blieb, war f\u00fcr mich das Debugging in AWS. Zwar war es dank CloudWatch m\u00f6glich, Ausgaben von Print-Statements in der Konsole zu loggen, Debugging im klassischen Sinne mithilfe von Breakpoints war jedoch nicht m\u00f6glich. Dadurch war ich mit einigen Problemen etwas l\u00e4nger besch\u00e4ftigt, als es meiner Meinung nach h\u00e4tte sein m\u00fcssen. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tests<\/h3>\n\n\n\n<p>Ich schrieb meine Tests erst, nachdem ich die App samt Backend bereits entwickelt hatte. Ich nehme mir vor, dies in den kommenden Projekten bereits zu einem fr\u00fcheren Zeitpunkt zu machen, da der Entwicklungsprozess von Tests durchaus profitieren kann und Fehler schneller auffallen, wodurch die Produktivit\u00e4t steigt.<br>Im Frontend erstellte ich Unittests und testete die Komponenten mit React Native UI-Tests. Im Backend erstellte ich ebenfalls Unittests f\u00fcr alle Bereiche der Anwendung sowie einen Integrationtest mit LocalStack, um die AWS-Komponenten in die Tests zu integrieren.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Meine Learnings<\/h3>\n\n\n\n<p>Auf technischer Ebene habe ich vor allem einen Einblick in das AWS-Universum bekommen. Auch f\u00fcr die Cross-Plattform-Entwicklung konnte ich durch die React-Native App ein Gef\u00fchl bekommen.<\/p>\n\n\n\n<p>Zudem konnte ich in diesem Projekt einige allgeine Learnings machen: Viele Aufgaben schienen am Anfang eher trivial, sollten sich bei genauerem Betrachten jedoch als umfangreich heruasstellen und waren mit dementsprechend viel Zeitaufwand verbunden.<br>In einigen Situationen h\u00e4tte ich durch fr\u00fchere Architektur\u00fcnerlegungen im Entwicklungsprozess evtl. Zeit sparen k\u00f6nnen. Auf der anderen Seite tauchten auch hier einige Probleme erst kurzfristig auf und w\u00e4ren bei der fr\u00fchzeitigen Planung m\u00f6glicherweise unentdeckt geblieben.<br>Generell habe ich in diesem Projekt gelernt, dass es f\u00fcr ein Endprodukt meist viele L\u00f6sungswege gibt und die Entwicklung, gerade auch bei Cloud-Technologien, viel mit dem Abw\u00e4gen zwischen verschiedenen Komponenten und deren Vor- und Nachteilen zu tun hat.<br>Etwas konkreter hatte ich immer wieder mit den Einflussfaktoren, die es bei asynchroner \u00dcbertragung zu beachten gilt, zu tun. Einige Probleme wurden durch Timeouts etc. verursacht und deren L\u00f6sung hing teilweise mit einem Umbau der kompletten Architektur zusammen. Ich denke, dass ich hierdurch in diesem Zusammenhang f\u00fcr die Zukunft sensibilisiert wurde.<br>Zuletzt war die Zeiteinteilung ein Aspekt, der nicht au\u00dfer Acht gelassen werden sollte. Ich habe das Projekt alleine durchgef\u00fchrt und es war dadurch eines der zeitaufw\u00e4ndigsten Projekte, die mich bisher besch\u00e4ftigten. Umso mehr kann ich behaupten, dass das Projekt einen Lerneffekt auf verschiedensten Ebenen hatte und ich mit dem Ergebnis zufrieden bin.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>F\u00fcr den Kurs &#8220;Software Development for Cloud Computing&#8221; wollte ich eine Anwendung entwickeln, mit der konkrete Aufgaben f\u00fcr ein gegebenes Lernziel generiert werden k\u00f6nnen. Der Nutzer stellt dabei Informationen zum Lernziel, sowie seines aktuellen Niveaus und der geplanten Lerndauer zur Verf\u00fcgung. Auf dieser Basis k\u00f6nnen dann die konkreten Aufgaben, die zum Erreichen des Ziels n\u00f6tig [&hellip;]<\/p>\n","protected":false},"author":1282,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"ppma_author":[1136],"class_list":["post-27939","post","type-post","status-publish","format-standard","hentry","category-allgemein"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":28637,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/02\/24\/potenziale-und-grenzen-ki-gestutzter-assistenzsysteme-in-der-product-owner-rolle-eine-empirische-fallstudie\/","url_meta":{"origin":27939,"position":0},"title":"Potenziale und Grenzen KI-gest\u00fctzter Assistenzsysteme in der Product Owner Rolle &#8211; eine Empirische Fallstudie","author":"Lisa-Marie Nohl","date":"24. February 2026","format":false,"excerpt":"Simeon Schulz, Ronja Brauchle, Lisa-Marie Nohl Kurzfassung: Ziel der Arbeit ist es herauszufinden, welches Potenzial k\u00fcnstliche Intelligenz bei der Arbeit eines Product Owners in der agilen Projektmanagement Methode Scrum hat. Dazu wurde eine empirische Fallstudie durchgef\u00fchrt, die unterschiedliche Tools nach Effizienz, Qualit\u00e4t, Usability und Integration bewertet. Die Ergebnisse zeigten, dass\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/02\/Bildschirmfoto-2026-02-24-um-13.21.11.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/02\/Bildschirmfoto-2026-02-24-um-13.21.11.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/02\/Bildschirmfoto-2026-02-24-um-13.21.11.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/02\/Bildschirmfoto-2026-02-24-um-13.21.11.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":28084,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2025\/09\/14\/springboot-zu-serverless-probleme-und-paradigmen\/","url_meta":{"origin":27939,"position":1},"title":"Springboot zu Serverless: Probleme und Paradigmen","author":"Julian Schniepp","date":"14. September 2025","format":false,"excerpt":"Im Rahmen der Vorlesung \u201eSoftware Development for Cloud\u00a0Computing\u201c sollte jedes Team ein eigenes Cloud\u2011Projekt umsetzen. Unser Projekt Taskflow sollte dabei ein serverloses Todo\u2011Management\u2011System werden. Ziel war es dabei, neue und vor allem industrierelevante Cloud\u2011Technologien praktisch zu erlernen. Der Backend\u2011Teil ist mit Spring\u2011Boot realisiert, welcher \u00fcber AWS\u00a0Lambda und API\u00a0Gateway bereitgestellt modular\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":24312,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/02\/28\/kann-man-einen-wissenschaftlichen-blogeintrag-rein-mithilfe-von-chatgpt-schreiben\/","url_meta":{"origin":27939,"position":2},"title":"Kann man einen wissenschaftlichen Blogeintrag rein mithilfe von ChatGPT schreiben?","author":"zack walker","date":"28. February 2023","format":false,"excerpt":"Einleitung In den letzten Jahren hat die K\u00fcnstliche Intelligenz (KI) einen enormen Aufschwung erlebt und ist zu einem wichtigen Teil unseres t\u00e4glichen Lebens geworden. KI wird f\u00fcr eine Vielzahl von Aufgaben eingesetzt - von der Bilderkennung bis hin zur Sprachverarbeitung. Eine der neuesten Anwendungen von KI ist ChatGPT, ein System\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-28-at-11.39.35.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-28-at-11.39.35.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-28-at-11.39.35.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/02\/Screenshot-2023-02-28-at-11.39.35.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":28173,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/01\/14\/autonome-ki-agenten-in-der-softwareentwicklung-architektur-patterns-theoretische-frameworks-und-design-entscheidungen\/","url_meta":{"origin":27939,"position":3},"title":"Autonome KI-Agenten in der Softwareentwicklung: Architektur-Patterns, theoretische Frameworks und Design-Entscheidungen","author":"Kay Kn\u00f6pfle","date":"14. January 2026","format":false,"excerpt":"Abstract This paper provides a systematic introduction to AI agents, covering core definitions and foundational architectural concepts. It examines tool integration, including operational principles, capabilities, and evaluation of AI coding agents, as well as the Model Context Protocol. The paper further analyzes memory systems as a key component for context\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"Schematische Darstellung des Groupchat Patterns","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/01\/groupchat.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/01\/groupchat.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/01\/groupchat.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/01\/groupchat.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":28461,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/02\/20\/das-alltagliche-automatisieren-das-menschliche-perfektionieren-die-transformation-des-scrum-masters-und-der-team-kommunikation-im-ki-gestutzten-agilen-umfeld\/","url_meta":{"origin":27939,"position":4},"title":"Das Allt\u00e4gliche automatisieren, das Menschliche perfektionieren: Die Transformation des Scrum-Masters und der Team-Kommunikation im KI-gest\u00fctzten agilen Umfeld","author":"Alice Ginnen","date":"20. February 2026","format":false,"excerpt":"Abstract Die zunehmende Nutzung von KI in der Softwareentwicklung ver\u00e4ndert grundlegend die bew\u00e4hrten agilen Methoden. In der vorliegenden Arbeit wird untersucht, inwiefern sich die Rolle des Scrum Masters und die Teamkommunikation durch den Einsatz von Large Language Models (LLMs) und autonomen Agenten ver\u00e4ndern. Die Analyse ergibt, dass ein zunehmender Anteil\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":24111,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/02\/26\/die-wachsende-macht-von-sprachmodellen-am-beispiel-chatgpt-und-bewertung-deren-skalierbarkeit\/","url_meta":{"origin":27939,"position":5},"title":"Die wachsende Macht von Sprachmodellen am Beispiel ChatGPT und Bewertung deren Skalierbarkeit","author":"Silas Blumenstock","date":"26. February 2023","format":false,"excerpt":"Die wachsende Macht von Sprachmodellen am Beispiel ChatGPT und Bewertung deren Skalierbarkeit","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/02\/image-19.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/02\/image-19.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/02\/image-19.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]}],"jetpack_sharing_enabled":true,"authors":[{"term_id":1136,"user_id":1282,"is_guest":0,"slug":"jonathan_aupperle","display_name":"Jonathan Aupperle","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/fd02f5d941b6f77ce5b4e7bf72522a01ceee1be35397552bb8d073a0f211d4d3?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/27939","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/users\/1282"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/comments?post=27939"}],"version-history":[{"count":47,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/27939\/revisions"}],"predecessor-version":[{"id":28010,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/27939\/revisions\/28010"}],"wp:attachment":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media?parent=27939"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/categories?post=27939"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/tags?post=27939"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/ppma_author?post=27939"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}