Haystack-MAS / index.html
aidn's picture
Update index.html
8cc6b43 verified
<!DOCTYPE html>
<html lang="de" class="scroll-smooth">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Konzept eines MAS mit Haystack 2.0</title>
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Highlight.js for Code Formatting -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/python.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/xml.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/bash.min.js"></script>
<!-- Google Fonts (Inter & Source Code Pro for HF feel) -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Source+Code+Pro:wght@400;500;600&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
sans: ['Inter', 'ui-sans-serif', 'system-ui', 'sans-serif'],
mono: ['Source Code Pro', 'ui-monospace', 'SFMono-Regular', 'monospace'],
},
colors: {
hfYellow: {
DEFAULT: '#FFD21E',
hover: '#F5C518',
light: '#FFF5CC'
},
hfGray: {
50: '#F9FAFB',
100: '#F3F4F6',
200: '#E5E7EB',
800: '#1F2937',
900: '#111827'
}
}
}
}
}
</script>
<style>
body { font-family: 'Inter', sans-serif; background-color: #ffffff; color: #111827; }
pre code { font-family: 'Source Code Pro', monospace; border-radius: 0.75rem; font-size: 0.875rem; padding: 1.5rem 1.25rem 1.25rem 1.25rem; }
.prose h2 { margin-top: 3.5rem; margin-bottom: 1.25rem; font-weight: 700; font-size: 1.75rem; color: #111827; border-bottom: 1px solid #E5E7EB; padding-bottom: 0.5rem; display: flex; align-items: center; gap: 0.5rem; }
.prose h3 { margin-top: 2.5rem; margin-bottom: 1rem; font-weight: 600; font-size: 1.25rem; color: #374151; }
.prose p { margin-bottom: 1.25rem; line-height: 1.8; color: #4B5563; }
.prose table { width: 100%; border-collapse: collapse; margin-bottom: 2rem; border-radius: 0.5rem; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
.prose th, .prose td { border: 1px solid #E5E7EB; padding: 1rem; text-align: left; font-size: 0.95rem; }
.prose th { background-color: #F9FAFB; font-weight: 600; color: #111827; }
/* Tooltip / Copy Button */
.copy-btn { position: absolute; top: 0.75rem; right: 0.75rem; background: rgba(255,255,255,0.1); color: #D1D5DB; border: 1px solid rgba(255,255,255,0.2); padding: 0.25rem 0.75rem; border-radius: 0.375rem; cursor: pointer; font-size: 0.75rem; transition: all 0.2s; z-index: 20; }
.copy-btn:hover { background: rgba(255,255,255,0.2); color: #fff; }
.code-wrapper { position: relative; margin-top: 1.5rem; margin-bottom: 2rem; border-radius: 0.75rem; background: #282c34; }
.file-label { position: absolute; top: -14px; left: 16px; background: #FFD21E; color: #111827; padding: 0.15rem 0.75rem; border-radius: 9999px; font-size: 0.75rem; font-weight: 700; z-index: 10; font-family: 'Source Code Pro', monospace; border: 2px solid #fff; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
/* Custom Scrollbar for Sidebar */
#sidebar::-webkit-scrollbar { width: 6px; }
#sidebar::-webkit-scrollbar-track { background: transparent; }
#sidebar::-webkit-scrollbar-thumb { background-color: #E5E7EB; border-radius: 20px; }
</style>
</head>
<body class="flex flex-col md:flex-row min-h-screen selection:bg-hfYellow selection:text-black">
<!-- Mobile Header -->
<div class="md:hidden bg-white border-b border-gray-200 p-4 flex justify-between items-center sticky top-0 z-50">
<div class="flex items-center gap-2">
<span class="text-2xl">🤗</span>
<h1 class="font-bold text-lg text-gray-900">MAS Konzept</h1>
</div>
<button id="mobile-menu-btn" class="text-gray-600 focus:outline-none hover:bg-gray-100 p-2 rounded-lg">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>
</button>
</div>
<!-- Sidebar Navigation -->
<nav id="sidebar" class="hidden md:flex flex-col w-full md:w-72 bg-gray-50 border-r border-gray-200 h-screen sticky top-0 overflow-y-auto shrink-0 transition-all duration-300 z-40">
<div class="p-6 hidden md:flex flex-col gap-2">
<div class="flex items-center gap-3">
<span class="text-3xl">🤗</span>
<h1 class="text-xl font-bold text-gray-900 tracking-tight leading-tight">Konzept eines MAS<br><span class="text-sm font-normal text-gray-500">mit Haystack 2.0</span></h1>
</div>
</div>
<div class="px-4 pb-4">
<div class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2 ml-3 mt-4">Architektur</div>
<ul class="space-y-1 text-sm font-medium">
<li><a href="#intro" class="block py-2 px-3 text-gray-600 rounded-lg hover:bg-gray-200 hover:text-gray-900 transition">1. Das Konzept & Framework</a></li>
<li><a href="#hf-infra" class="block py-2 px-3 text-gray-600 rounded-lg hover:bg-gray-200 hover:text-gray-900 transition">2. Hugging Face Inference</a></li>
</ul>
<div class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2 ml-3 mt-6">Die Agenten (Pipelines)</div>
<ul class="space-y-1 text-sm font-medium">
<li><a href="#agent1" class="block py-2 px-3 text-gray-600 rounded-lg hover:bg-gray-200 hover:text-gray-900 transition">3. Agent 1: Forschung & Suche</a></li>
<li><a href="#agent2" class="block py-2 px-3 text-gray-600 rounded-lg hover:bg-gray-200 hover:text-gray-900 transition">4. Agent 2: Struktur & Pydantic</a></li>
<li><a href="#agent3" class="block py-2 px-3 text-gray-600 rounded-lg hover:bg-gray-200 hover:text-gray-900 transition">5. Agent 3: Visionär (Bildgen.)</a></li>
<li><a href="#agent4" class="block py-2 px-3 text-gray-600 rounded-lg hover:bg-gray-200 hover:text-gray-900 transition">6. Agent 4: Meta-Aggregator</a></li>
</ul>
<div class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2 ml-3 mt-6">Orchestrierung & Code</div>
<ul class="space-y-1 text-sm font-medium">
<li><a href="#orchestration" class="block py-2 px-3 text-gray-600 rounded-lg hover:bg-gray-200 hover:text-gray-900 transition">7. Routing & Tool-Calling</a></li>
<li><a href="#repo" class="block py-2 px-3 text-gray-600 rounded-lg hover:bg-gray-200 hover:text-gray-900 transition">8. Repositorystruktur</a></li>
<li><a href="#outlook" class="flex items-center gap-2 mt-2 py-2 px-3 bg-gray-900 text-white rounded-lg hover:bg-gray-800 transition">
<svg class="w-4 h-4 text-hfYellow" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg>
9. Fazit: Die KI-Küchenbrigade
</a></li>
</ul>
</div>
</nav>
<!-- Main Content -->
<main class="flex-1 w-full max-w-4xl mx-auto p-6 md:p-10 lg:p-14">
<div class="prose max-w-none">
<!-- Hero -->
<div class="bg-hfYellow/10 border border-hfYellow rounded-2xl p-8 mb-12 shadow-sm">
<div class="flex items-center gap-3 mb-4">
<span class="text-4xl">🥘</span>
<h1 class="text-3xl font-bold text-gray-900 m-0">Architektur eines Kulinarischen MAS</h1>
</div>
<p class="text-gray-700 text-lg leading-relaxed m-0">Ein Deep-Dive in die Orchestrierung von Multi-Agenten-Systemen (MAS) für <strong>"The Infinite Cookbook"</strong>. Wir zerlegen komplexe Aufgaben (Recherche, Strukturierung, Bildgenerierung, Layout) in spezialisierte Haystack 2.0 Pipelines und verbinden sie über Hugging Face Open-Source LLMs zu einem autonomen System.</p>
</div>
<section id="intro">
<h2><span>🏗️</span> 1. Das Konzept: Haystack 2.0</h2>
<p>Die Evolution der KI verlangt nach neuen Architekturen. Der Übergang von Haystack 1.x zu 2.0 markiert einen Paradigmenwechsel: Frühere Versionen waren auf lineare Ketten ausgelegt, Haystack 2.0 führt <strong>Komponenten und Pipelines als dynamische Rechengraphen</strong> ein.</p>
<p>Diese Graphen unterstützen Kontrollflüsse, Schleifen und präzises Routing. Ein Agent in diesem Ökosystem ist weit mehr als ein Chatbot; er ist ein System, das ein LLM als Steuerungsorgan nutzt, um Aufgaben zu planen und an spezialisierte Sub-Pipelines (andere Agenten) zu delegieren. Typprüfung an den Ein- und Ausgabesockets sichert dabei die Stabilität vor der Laufzeit.</p>
</section>
<section id="hf-infra">
<h2><span>🤗</span> 2. Hugging Face Inference Provider</h2>
<p>Hugging Face ist der zentrale Marktplatz für Open-Source-Intelligenz. Im Juli 2025 stellte die Inference API auf <code>chat_completion</code>-Endpunkte um. Haystack bindet diese Modelle über die <code>HuggingFaceAPIChatGenerator</code>-Komponente ein. Durch dynamische Suffixe wie <code>:fastest</code> oder Provider-Wahl können wir Lasten optimieren:</p>
<div class="overflow-x-auto">
<table>
<thead>
<tr>
<th>Infrastruktur-Option</th>
<th>Charakteristika</th>
<th>Anwendungsfall im MAS</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Serverless Inference API</strong></td>
<td>Kostenlos/Rate-limited, schnell</td>
<td>Prototyping und einfache Zusammenfassungen (z.B. Qwen 72B).</td>
</tr>
<tr>
<td><strong>Inference Endpoints</strong></td>
<td>Dedizierte Instanzen, /h Abrechnung</td>
<td>Produktion, garantierte Latenz, Bildgenerierung (SDXL / FLUX).</td>
</tr>
<tr>
<td><strong>Text Generation Inference (TGI)</strong></td>
<td>Optimiertes Serving, JSON-Guiding</td>
<td>Komplexe Datenextraktion mit strikter Schema-Einhaltung.</td>
</tr>
</tbody>
</table>
</div>
</section>
<section id="agent1">
<h2><span>🔍</span> 3. Agent 1: Forschung & Suche</h2>
<p>Die erste Phase ist die <em>Deep Research Phase</em>. Dieser Agent durchsucht das Web iterativ nach authentischen Rezepten, regionalen Varianten und historischen Hintergründen. Er nutzt Tools, um Links zu besuchen, HTML zu bereinigen und die Ergebnisse nach Relevanz (Context Optimization) zu ranken, bevor sie ans LLM gehen.</p>
<div class="code-wrapper">
<div class="file-label">agents/researcher.py</div>
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
<pre><code class="language-python">from haystack import Pipeline
from haystack.components.websearch import SerperDevWebSearch
from haystack.components.fetchers import LinkContentFetcher
from haystack.components.converters import HTMLToDocument
from haystack.components.rankers import TransformersSimilarityRanker
def build_research_pipeline() -> Pipeline:
pipe = Pipeline()
# Komponenten initialisieren
pipe.add_component("search", SerperDevWebSearch(api_key="DEIN_API_KEY"))
pipe.add_component("fetcher", LinkContentFetcher())
pipe.add_component("html_converter", HTMLToDocument())
# Der Ranker sortiert Dokumente nach Relevanz zur Suchanfrage aus
pipe.add_component("ranker", TransformersSimilarityRanker(model="cross-encoder/ms-marco-MiniLM-L-6-v2"))
# Den gerichteten Graphen aufbauen
pipe.connect("search.links", "fetcher.urls")
pipe.connect("fetcher.streams", "html_converter.sources")
pipe.connect("html_converter.documents", "ranker.documents")
return pipe</code></pre>
</div>
</section>
<section id="agent2">
<h2><span>📋</span> 4. Agent 2: Struktur & Pydantic</h2>
<p>Der Zusammenfassungs-Agent wandelt die unstrukturierten Forschungsnotizen in ein präzises, maschinenlesbares Rezept um. Das ist kritisch, da Inkonsistenzen das HTML-Layout gefährden. Haystack 2.0 erzwingt strukturierte Ausgaben über <strong>Pydantic-Modelle</strong> (besonders mächtig in Kombination mit Hugging Face TGI-Instanzen).</p>
<div class="code-wrapper">
<div class="file-label">schemas/recipe.py</div>
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
<pre><code class="language-python">from pydantic import BaseModel
from typing import List, Dict, Literal
# Strikte Typisierung eliminiert Halluzinationen in der Struktur
class Ingredient(BaseModel):
name: str
amount: float
unit: str
class RecipeStructure(BaseModel):
recipe_title: str
servings: int
ingredients: List[Ingredient]
instructions: List[str]
nutrients: Dict[str, float]
difficulty: Literal["Einfach", "Mittel", "Schwer"]
# Nutzungshinweis für die Pipeline:
# generator = HuggingFaceAPIChatGenerator(
# api_type="text_generation_inference",
# generation_kwargs={"response_format": RecipeStructure.schema_json()}
# )</code></pre>
</div>
</section>
<section id="agent3">
<h2><span>🎨</span> 5. Agent 3: Visionär (Bildgenerierung)</h2>
<p>Ein Kochbuch braucht Ästhetik. Da Sprachmodelle keinen Text in Bilder konvertieren, implementieren wir eine <strong>benutzerdefinierte Haystack-Komponente</strong>. Diese nimmt den Rezepttitel auf, optimiert den Prompt ("Professionelle Food-Fotografie, Makro...") und steuert via <code>diffusers</code> ein Modell wie Stable Diffusion XL oder FLUX an.</p>
<div class="code-wrapper">
<div class="file-label">components/image_generator.py</div>
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
<pre><code class="language-python">from haystack import component
from haystack.dataclasses import ImageContent
# import diffusers ...
@component
class StableDiffusionGenerator:
def __init__(self, model_id="stabilityai/stable-diffusion-xl-base-1.0"):
self.model_id = model_id
# Initialisierung z.B. Pipeline Laden inkl. FP16 Optimierung
# Definition des Output-Sockets für die Validierung vor der Laufzeit
@component.output_types(image=ImageContent)
def run(self, prompt: str):
# image = self.pipe(prompt).images[0]
# base64_str = convert_to_base64(image)
# Rückgabe als Haystack 2.0 Multimodal Objekt
return {"image": ImageContent.from_base64(base64_str)}</code></pre>
</div>
</section>
<section id="agent4">
<h2><span>💻</span> 6. Agent 4: Meta-Aggregator (HTML)</h2>
<p>Der letzte Agent orchestriert die Präsentation. Er empfängt das strukturierte Rezept (als Dictionary/JSON) und das generierte Bild (als Base64) und verpackt beides über <strong>Jinja2-Templating</strong>.</p>
<div class="code-wrapper">
<div class="file-label">templates/recipe_card.html</div>
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
<pre><code class="language-xml">&lt;!-- Das Template wird vom HTML-Agenten mit Daten befüllt --&gt;
&lt;div class="recipe-card"&gt;
&lt;h1&gt;{{ recipe_title }}&lt;/h1&gt;
&lt;!-- Base64 Einbettung erspart externe Bild-Hostings --&gt;
&lt;img src="data:image/png;base64,{{ image_base64 }}" alt="{{ recipe_title }}"&gt;
&lt;div class="meta"&gt;
&lt;span&gt;Schwierigkeit: {{ difficulty }}&lt;/span&gt;
&lt;/div&gt;
&lt;h3&gt;Zutaten&lt;/h3&gt;
&lt;ul&gt;
{% for ingredient in ingredients %}
&lt;li&gt;{{ ingredient.amount }} {{ ingredient.unit }} {{ ingredient.name}}&lt;/li&gt;
{% endfor %}
&lt;/ul&gt;
&lt;h3&gt;Zubereitung&lt;/h3&gt;
&lt;ol&gt;
{% for step in instructions %}
&lt;li&gt;{{ step }}&lt;/li&gt;
{% endfor %}
&lt;/ol&gt;
&lt;/div&gt;</code></pre>
</div>
</section>
<section id="orchestration">
<h2><span>🚦</span> 7. Orchestrierung & Fehlerbehandlung</h2>
<p>Um diese Agenten zu vereinen, nutzen wir den <strong>"Agent-as-a-Tool"</strong>-Ansatz. Ein Koordinator-Agent kapselt die Pipelines in Werkzeugen. So kann das Haupt-LLM dynamisch entscheiden, wann es recherchiert und wann es Bilder generiert.</p>
<p>Für Robustheit sorgt der <code>ConditionalRouter</code>. Liefert ein Tool einen Fehler (z.B. keine Suchergebnisse), leitet der Router den Datenfluss um, sodass das LLM seinen Such-Prompt anpassen kann, anstatt abzustürzen.</p>
<div class="code-wrapper">
<div class="file-label">tools/agent_tools.py</div>
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
<pre><code class="language-python">from haystack.tools import Tool
from haystack.components.routers import ConditionalRouter
from agents.researcher import build_research_pipeline
# Pipeline laden
research_pipe = build_research_pipeline()
# Pipeline als aufrufbares Werkzeug für das LLM verpacken
research_tool = Tool(
name="research_tool",
description="Durchsucht das Web nach authentischen Rezepten.",
parameters={"query": {"type": "string"}},
function=research_pipe.run
)
# Fehlerbehandlung: Ein Router, der den Pfad basierend auf Tool-Erfolg wählt
routes = [
{
"condition": "{{ 'error' in tool_result.text | lower }}",
"output": "{{ tool_result }}",
"output_name": "error_route",
"output_type": str
},
{
"condition": "{{ 'error' not in tool_result.text | lower }}",
"output": "{{ tool_result }}",
"output_name": "success_route",
"output_type": str
}
]
router = ConditionalRouter(routes)</code></pre>
</div>
</section>
<!-- KAPITEL 8: REPOSITORY UND CODE -->
<section id="repo">
<h2><span>📁</span> 8. Repository-Struktur: Der Master-Plan</h2>
<p>Alle Code-Schnipsel aus Kapitel 3 bis 7 fügen sich nun zusammen. Ein komplexes MAS sollte <strong>niemals ein Monolith</strong> sein (alles in einem Skript). Eine monolithische Architektur würde das Testen einzelner Pipelines fast unmöglich machen und zu Spaghetti-Code beim Routing führen.</p>
<p>Dank der modularen Architektur von Haystack 2.0 spiegelt sich die fachliche Trennung direkt im Repository wider:</p>
<div class="bg-gray-50 border border-gray-200 rounded-lg p-5 mb-8 font-mono text-sm text-gray-700 leading-relaxed shadow-sm">
infinite-cookbook/<br>
├── <span class="font-bold text-gray-900">schemas/</span><br>
│ └── <span class="text-blue-600">recipe.py</span> <span class="text-gray-400 italic"># (Kapitel 4) Pydantic Modelle</span><br>
├── <span class="font-bold text-gray-900">components/</span><br>
│ └── <span class="text-blue-600">image_generator.py</span> <span class="text-gray-400 italic"># (Kapitel 5) Custom @component</span><br>
├── <span class="font-bold text-gray-900">templates/</span><br>
│ └── <span class="text-blue-600">recipe_card.html</span> <span class="text-gray-400 italic"># (Kapitel 6) Jinja2 Template</span><br>
├── <span class="font-bold text-gray-900">agents/</span><br>
│ ├── <span class="text-blue-600">researcher.py</span> <span class="text-gray-400 italic"># (Kapitel 3) Web-Search Pipeline</span><br>
│ └── <span class="text-gray-500">structurer.py ...</span><br>
├── <span class="font-bold text-gray-900">tools/</span><br>
│ └── <span class="text-blue-600">agent_tools.py</span> <span class="text-gray-400 italic"># (Kapitel 7) Pipeline -> Tool Wrapper</span><br>
└── <span class="text-blue-600 font-bold">main.py</span> <span class="text-gray-400 italic"># Orchestrierungs-Loop (siehe unten)</span>
</div>
<h3>Das Herzstück: <code>main.py</code></h3>
<p>Weil wir alle Komplexität in die Unterordner ausgelagert haben, ist die <code>main.py</code> unglaublich elegant. Sie initialisiert das Haupt-LLM, importiert die fertige Werkzeugkiste und startet die Interaktions-Schleife.</p>
<div class="code-wrapper mt-4">
<div class="file-label">main.py</div>
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
<pre><code class="language-python">import os
from haystack import Pipeline
from haystack.components.generators.chat import HuggingFaceAPIChatGenerator
from haystack.components.tools import ToolInvoker
from haystack.dataclasses import ChatMessage
# Der saubere Import aus unserer Architektur (Kapitel 7)
from tools.agent_tools import cookbook_tools
def main():
# 1. Der Koordinator: Ein starkes Modell (z.B. Qwen), das Tool-Calling beherrscht
llm = HuggingFaceAPIChatGenerator(
api_type="serverless_inference_api",
model="Qwen/Qwen2.5-72B-Instruct",
tools=cookbook_tools
)
# 2. Der Invoker: Führt die vom LLM gewählten Tools aus
invoker = ToolInvoker(tools=cookbook_tools)
# 3. Der Orchestrierungs-Graph aufbauen
coordinator = Pipeline()
coordinator.add_component("llm", llm)
coordinator.add_component("invoker", invoker)
# Zyklische Verbindung für iteratives Arbeiten
coordinator.connect("llm.replies", "invoker.messages")
coordinator.connect("invoker.tool_messages", "llm.messages")
# 4. System Start
user_prompt = "Erstelle ein Rezept für ein thailändisches grünes Curry samt HTML und Bild."
messages = [ChatMessage.from_user(user_prompt)]
print(f"🤖 Koordinator startet Aufgabe: {user_prompt}")
# Run Loop
result = coordinator.run({"llm": {"messages": messages}})
print("Fertiges Ergebnis:", result["llm"]["replies"][0].text)
if __name__ == "__main__":
main()</code></pre>
</div>
<div class="mt-8 p-5 bg-blue-50/50 rounded-xl text-sm text-gray-700 border border-blue-100 flex items-start gap-4 shadow-sm">
<span class="text-2xl mt-1">💡</span>
<div>
<strong class="text-gray-900 block mb-1">Die Architektur-Philosophie:</strong>
Diese Aufteilung erlaubt es dir, das Modell in <code>main.py</code> auszutauschen, die Such-Logik in <code>researcher.py</code> komplett neu zu schreiben oder an der HTML-Karte zu basteln, ohne dass die anderen Teile des Multi-Agenten-Systems zerbrechen. Das ist die Stärke von Haystack 2.0!
</div>
</div>
</section>
<!-- NEUES GRAND FINALE (KERNPRINZIP MAS & KÜCHENMETAPHER) -->
<section id="outlook" class="mt-20 pt-8 border-t border-gray-200">
<div class="bg-gray-900 text-white rounded-3xl p-8 md:p-12 shadow-2xl relative overflow-hidden">
<!-- Dekoration -->
<div class="absolute -top-24 -right-24 w-64 h-64 bg-hfYellow rounded-full mix-blend-multiply filter blur-3xl opacity-20"></div>
<div class="absolute -bottom-24 -left-24 w-64 h-64 bg-blue-500 rounded-full mix-blend-multiply filter blur-3xl opacity-20"></div>
<div class="relative z-10">
<div class="flex items-center gap-3 mb-6">
<span class="text-3xl">👨‍🍳</span>
<h2 class="text-3xl font-bold m-0 border-none !text-white">Fazit: Die KI-Küchenbrigade</h2>
</div>
<p class="text-gray-300 text-lg leading-relaxed max-w-2xl mb-6">
Man sagt oft: <em>»Viele Köche verderben den Brei.«</em> In der Welt der Künstlichen Intelligenz gilt jedoch genau das Gegenteil – vorausgesetzt, man hat die richtige Architektur.
</p>
<p class="text-gray-300 text-lg leading-relaxed max-w-2xl mb-8">
Das "Infinite Cookbook" illustriert das <strong>Grundprinzip eines Multi-Agenten-Systems (MAS)</strong> perfekt. Anstatt ein einziges, riesiges "Gott-Modell" mit einem gigantischen Prompt zu überlasten (und zu hoffen, dass es gleichzeitig fehlerfrei recherchiert, programmiert, layoutet und malt), etablieren wir eine hochspezialisierte, arbeitsteilige Küchenbrigade:
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-10">
<div class="bg-white/5 border border-white/10 rounded-xl p-5 hover:bg-white/10 transition">
<h3 class="!text-white text-base font-semibold mt-0 mb-2 flex items-center gap-2">
<span>👔</span> Der Küchenchef (Koordinator)
</h3>
<p class="text-gray-400 text-sm m-0">
Er kocht nicht selbst. Er nimmt die Bestellung des Gastes entgegen, plant die Schritte und delegiert die Aufgaben an sein Team (Tool Calling).
</p>
</div>
<div class="bg-white/5 border border-white/10 rounded-xl p-5 hover:bg-white/10 transition">
<h3 class="!text-white text-base font-semibold mt-0 mb-2 flex items-center gap-2">
<span>🛒</span> Der Einkäufer (Forschung)
</h3>
<p class="text-gray-400 text-sm m-0">
Er weiß, auf welchen Märkten (Web) es die besten und authentischsten Zutaten (Daten) gibt. Er sortiert den Müll aus und bringt nur das Beste in die Küche.
</p>
</div>
<div class="bg-white/5 border border-white/10 rounded-xl p-5 hover:bg-white/10 transition">
<h3 class="!text-white text-base font-semibold mt-0 mb-2 flex items-center gap-2">
<span>🔪</span> Der Postenchef (Struktur)
</h3>
<p class="text-gray-400 text-sm m-0">
Er ist besessen von Präzision. Er nimmt die losen Zutaten und formatiert sie exakt nach der strikten Pydantic-Rezeptvorlage. Keine Halluzinationen, nur Fakten.
</p>
</div>
<div class="bg-white/5 border border-white/10 rounded-xl p-5 hover:bg-white/10 transition">
<h3 class="!text-white text-base font-semibold mt-0 mb-2 flex items-center gap-2">
<span>📸</span> Der Food-Stylist (Visionär)
</h3>
<p class="text-gray-400 text-sm m-0">
Er interessiert sich nicht für Grammatik oder HTML. Er malt mit Diffusionsmodellen atemberaubende Bilder, die das Gericht perfekt in Szene setzen.
</p>
</div>
</div>
<p class="text-gray-300 text-lg leading-relaxed max-w-2xl mb-8 font-medium border-l-4 border-hfYellow pl-4">
Die wahre Stärke eines MAS ist die <strong>Isolation von Komplexität</strong>. Wenn das HTML bricht, reparieren wir den Meta-Agenten. Wenn wir ein besseres Open-Source-Modell für JSON finden, tauschen wir den Postenchef aus, ohne dass der Rest der Küche stehenbleibt. <span class="text-hfYellow">Haystack 2.0 liefert uns dafür die Küche – und die Infrastruktur von Hugging Face das Personal.</span>
</p>
<div class="flex flex-wrap items-center gap-4">
<a href="https://haystack.deepset.ai/" target="_blank" class="px-6 py-3 bg-hfYellow text-gray-900 font-bold rounded-lg hover:bg-hfYellow-hover transition-colors flex items-center gap-2 no-underline">
Erforsche Haystack 2.0
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path></svg>
</a>
<a href="https://huggingface.co/models" target="_blank" class="px-6 py-3 bg-gray-800 text-white border border-gray-700 font-semibold rounded-lg hover:bg-gray-700 transition-colors flex items-center gap-2 no-underline">
🤗 HF Modelle entdecken
</a>
</div>
</div>
</div>
</section>
<!-- ÜBERARBEITETER FOOTER -->
<footer class="mt-16 py-8 border-t border-gray-200 flex flex-col md:flex-row items-center justify-between gap-6">
<div class="flex items-center gap-3">
<span class="text-2xl opacity-80">🤗</span>
<p class="text-sm text-gray-500 m-0 leading-tight">
<strong>The Infinite Cookbook Konzept</strong><br>
Ein Architektur-Beispiel für Multi-Agenten-Systeme.
</p>
</div>
<div class="flex items-center gap-6 text-sm font-medium text-gray-500">
<a href="#" class="hover:text-gray-900 transition-colors no-underline">Source PDF</a>
<a href="https://github.com/deepset-ai/haystack" target="_blank" class="hover:text-gray-900 transition-colors no-underline">Haystack GitHub</a>
<a href="https://huggingface.co/docs/inference-providers/index" target="_blank" class="hover:text-gray-900 transition-colors no-underline">Inference Docs</a>
</div>
</footer>
</div>
</main>
<script>
// Syntax Highlighting initialisieren
document.addEventListener('DOMContentLoaded', (event) => {
hljs.highlightAll();
});
// Mobile Menu Toggle
const btn = document.getElementById('mobile-menu-btn');
const sidebar = document.getElementById('sidebar');
btn.addEventListener('click', () => {
sidebar.classList.toggle('hidden');
});
// Smooth scroll adjustment for fixed header
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
if(window.innerWidth < 768) {
sidebar.classList.add('hidden');
}
// Active State Styling Update
document.querySelectorAll('#sidebar a').forEach(a => {
a.classList.remove('bg-hfYellow/20', 'text-yellow-800', 'font-semibold', 'bg-gray-900', 'text-white', 'hover:bg-gray-800');
if (a.getAttribute('href') === '#outlook') {
a.classList.add('bg-gray-900', 'text-white', 'hover:bg-gray-800');
} else {
a.classList.add('text-gray-600');
}
});
if(this.getAttribute('href') !== '#outlook' && this.getAttribute('href') !== '#repo') {
this.classList.remove('text-gray-600');
this.classList.add('bg-hfYellow/20', 'text-yellow-800', 'font-semibold');
} else if (this.getAttribute('href') === '#repo') {
this.classList.remove('text-gray-600');
this.classList.add('bg-hfYellow/20', 'text-yellow-900', 'font-semibold');
}
document.querySelector(this.getAttribute('href')).scrollIntoView({
behavior: 'smooth'
});
});
});
// Copy to clipboard function
function copyCode(button) {
const codeBlock = button.nextElementSibling.querySelector('code');
const textToCopy = codeBlock.innerText;
const textArea = document.createElement("textarea");
textArea.value = textToCopy;
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = button.innerText;
button.innerText = 'Copied!';
button.classList.add('bg-green-600', 'text-white', 'border-green-600');
setTimeout(() => {
button.innerText = originalText;
button.classList.remove('bg-green-600', 'text-white', 'border-green-600');
}, 2000);
} catch (err) {
console.error('Kopieren fehlgeschlagen', err);
}
document.body.removeChild(textArea);
}
</script>
</body>
</html>