Spaces:
Running
Running
Update index.html
Browse files- index.html +268 -214
index.html
CHANGED
|
@@ -3,31 +3,42 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
-
<title>
|
| 7 |
|
| 8 |
<!-- Tailwind CSS -->
|
| 9 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 10 |
|
| 11 |
-
<!-- Highlight.js for Code Formatting -->
|
| 12 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
|
| 13 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
| 14 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/python.min.js"></script>
|
| 15 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/xml.min.js"></script>
|
|
|
|
| 16 |
|
| 17 |
-
<!-- Google Fonts -->
|
| 18 |
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=
|
| 19 |
|
| 20 |
<script>
|
| 21 |
tailwind.config = {
|
| 22 |
theme: {
|
| 23 |
extend: {
|
| 24 |
fontFamily: {
|
| 25 |
-
sans: ['Inter', 'sans-serif'],
|
| 26 |
-
mono: ['
|
| 27 |
},
|
| 28 |
colors: {
|
| 29 |
-
|
| 30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
}
|
| 32 |
}
|
| 33 |
}
|
|
@@ -35,95 +46,121 @@
|
|
| 35 |
</script>
|
| 36 |
|
| 37 |
<style>
|
| 38 |
-
body { font-family: 'Inter', sans-serif; }
|
| 39 |
-
pre code { font-family: '
|
| 40 |
-
.prose h2 { margin-top:
|
| 41 |
-
.prose h3 { margin-top: 2rem; margin-bottom:
|
| 42 |
-
.prose p { margin-bottom: 1.25rem; line-height: 1.
|
| 43 |
-
.prose table { width: 100%; border-collapse: collapse; margin-bottom: 2rem; }
|
| 44 |
-
.prose th, .prose td { border: 1px solid #
|
| 45 |
-
.prose th { background-color: #
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
</style>
|
| 50 |
</head>
|
| 51 |
-
<body class="
|
| 52 |
|
| 53 |
<!-- Mobile Header -->
|
| 54 |
-
<div class="md:hidden bg-
|
| 55 |
-
<
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
| 57 |
<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>
|
| 58 |
</button>
|
| 59 |
</div>
|
| 60 |
|
| 61 |
<!-- Sidebar Navigation -->
|
| 62 |
-
<nav id="sidebar" class="hidden md:flex flex-col w-full md:w-
|
| 63 |
-
<div class="p-6 hidden md:
|
| 64 |
-
<
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
</div>
|
| 67 |
-
<ul class="flex-1 px-4 pb-6 space-y-2 text-sm">
|
| 68 |
-
<li><a href="#intro" class="block py-2 px-3 rounded hover:bg-slate-800 hover:text-white transition">1. Einleitung & Architektur</a></li>
|
| 69 |
-
<li><a href="#hf-infra" class="block py-2 px-3 rounded hover:bg-slate-800 hover:text-white transition">2. Hugging Face Infrastruktur</a></li>
|
| 70 |
-
<li><a href="#agent1" class="block py-2 px-3 rounded hover:bg-slate-800 hover:text-white transition">3. Agent 1: Forschung & Suche</a></li>
|
| 71 |
-
<li><a href="#agent2" class="block py-2 px-3 rounded hover:bg-slate-800 hover:text-white transition">4. Agent 2: Struktur & Pydantic</a></li>
|
| 72 |
-
<li><a href="#agent3" class="block py-2 px-3 rounded hover:bg-slate-800 hover:text-white transition">5. Agent 3: Visionär (Bildgen.)</a></li>
|
| 73 |
-
<li><a href="#agent4" class="block py-2 px-3 rounded hover:bg-slate-800 hover:text-white transition">6. Agent 4: Meta-Aggregator (HTML)</a></li>
|
| 74 |
-
<li><a href="#orchestration" class="block py-2 px-3 rounded hover:bg-slate-800 hover:text-white transition">7. Orchestrierung & Fehlerbehandlung</a></li>
|
| 75 |
-
</ul>
|
| 76 |
</nav>
|
| 77 |
|
| 78 |
<!-- Main Content -->
|
| 79 |
-
<main class="flex-1 w-full max-w-4xl mx-auto p-6 md:p-10 lg:p-
|
| 80 |
<div class="prose max-w-none">
|
| 81 |
|
| 82 |
<!-- Hero -->
|
| 83 |
-
<div class="bg-
|
| 84 |
-
<
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
| 86 |
</div>
|
| 87 |
|
| 88 |
<section id="intro">
|
| 89 |
-
<h2>1.
|
| 90 |
-
<p>Der
|
| 91 |
-
<p>Anstatt ein einzelnes, überfordertes LLM zu nutzen, orchestrieren wir eine Koalition spezialisierter Einheiten. Typprüfung an den Ein- und Ausgabesockets sichert die Stabilität.</p>
|
| 92 |
</section>
|
| 93 |
|
| 94 |
<section id="hf-infra">
|
| 95 |
-
<h2>2. Hugging Face Inference Provider</h2>
|
| 96 |
-
<p>
|
| 97 |
|
| 98 |
<div class="overflow-x-auto">
|
| 99 |
<table>
|
| 100 |
<thead>
|
| 101 |
<tr>
|
| 102 |
-
<th>Infrastruktur
|
| 103 |
<th>Charakteristika</th>
|
| 104 |
-
<th>
|
| 105 |
</tr>
|
| 106 |
</thead>
|
| 107 |
<tbody>
|
| 108 |
<tr>
|
| 109 |
-
<td><strong>Serverless
|
| 110 |
-
<td>Kostenlos
|
| 111 |
-
<td
|
| 112 |
</tr>
|
| 113 |
<tr>
|
| 114 |
<td><strong>Inference Endpoints</strong></td>
|
| 115 |
-
<td>
|
| 116 |
-
<td
|
| 117 |
-
</tr>
|
| 118 |
-
<tr>
|
| 119 |
-
<td><strong>Text Generation Inference (TGI)</strong></td>
|
| 120 |
-
<td>Optimiertes Serving, unterstützt JSON-Guiding</td>
|
| 121 |
-
<td>Komplexe Datenextraktion mit strikter Schema-Einhaltung.</td>
|
| 122 |
</tr>
|
| 123 |
<tr>
|
| 124 |
-
<td><strong>
|
| 125 |
-
<td>
|
| 126 |
-
<td
|
| 127 |
</tr>
|
| 128 |
</tbody>
|
| 129 |
</table>
|
|
@@ -131,47 +168,66 @@
|
|
| 131 |
</section>
|
| 132 |
|
| 133 |
<section id="agent1">
|
| 134 |
-
<h2>3. Agent 1:
|
| 135 |
-
<p>Dieser Agent
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
<button class="copy-btn" onclick="copyCode(this)">Kopieren</button>
|
| 139 |
<pre><code class="language-python">from haystack import Pipeline
|
| 140 |
from haystack.components.websearch import SerperDevWebSearch
|
| 141 |
-
|
| 142 |
-
from haystack.components.converters import HTMLToDocument
|
| 143 |
-
from haystack.components.rankers import TransformersSimilarityRanker
|
| 144 |
-
|
| 145 |
-
# Pipeline-Definition für den Forschungs-Agenten
|
| 146 |
research_pipe = Pipeline()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
research_pipe.add_component("ranker", TransformersSimilarityRanker(model="cross-encoder/ms-marco-MiniLM-L-6-v2"))
|
| 153 |
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
</code></
|
| 162 |
-
</div>
|
| 163 |
</section>
|
| 164 |
|
| 165 |
-
<
|
| 166 |
-
|
| 167 |
-
<
|
|
|
|
|
|
|
|
|
|
| 168 |
|
| 169 |
-
<div class="
|
| 170 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
<pre><code class="language-python">from pydantic import BaseModel
|
| 172 |
-
from typing import List,
|
| 173 |
|
| 174 |
-
# Definition des Pydantic-Schemas laut Spezifikation
|
| 175 |
class Ingredient(BaseModel):
|
| 176 |
name: str
|
| 177 |
amount: float
|
|
@@ -182,139 +238,129 @@ class RecipeStructure(BaseModel):
|
|
| 182 |
servings: int
|
| 183 |
ingredients: List[Ingredient]
|
| 184 |
instructions: List[str]
|
| 185 |
-
|
| 186 |
-
difficulty: Literal["Einfach", "Mittel", "Schwer"]
|
| 187 |
-
|
| 188 |
-
# Nutzung im HuggingFace Chat Generator (mit TGI & JSON Guiding)
|
| 189 |
-
# generator = HuggingFaceAPIChatGenerator(
|
| 190 |
-
# api_type="text_generation_inference",
|
| 191 |
-
# generation_kwargs={"response_format": RecipeStructure.schema_json()}
|
| 192 |
-
# )
|
| 193 |
-
</code></pre>
|
| 194 |
</div>
|
| 195 |
-
<p>Durch die Erzwingung dieses Schemas werden Halluzinationen in der Struktur eliminiert. Der Agent wird zudem angewiesen, <em>keine eigenen Fakten zu erfinden</em>, sondern sich streng an den Kontext von Agent 1 zu halten.</p>
|
| 196 |
-
</section>
|
| 197 |
|
| 198 |
-
|
| 199 |
-
<
|
| 200 |
-
<
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
<
|
| 204 |
-
|
| 205 |
-
from haystack.
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
# Rückgabe als Haystack 2.0 ImageContent Objekt
|
| 224 |
-
return {"image": ImageContent.from_base64(base64_str)}
|
| 225 |
-
</code></pre>
|
| 226 |
</div>
|
| 227 |
-
</section>
|
| 228 |
|
| 229 |
-
|
| 230 |
-
<
|
| 231 |
-
<
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
<
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
|
| 239 |
-
|
| 240 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 241 |
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
|
|
|
|
|
|
|
|
|
| 246 |
|
| 247 |
-
|
| 248 |
-
<ul>
|
| 249 |
-
{% for ingredient in ingredients %}
|
| 250 |
-
<li>{{ ingredient.amount }} {{ ingredient.unit }} {{ ingredient.name}}</li>
|
| 251 |
-
{% endfor %}
|
| 252 |
-
</ul>
|
| 253 |
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
</div></code></pre>
|
| 261 |
-
</div>
|
| 262 |
-
</section>
|
| 263 |
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
<
|
| 267 |
-
<ol class="list-decimal pl-6 mb-6 space-y-2 text-slate-600">
|
| 268 |
-
<li><strong>Recherche-Delegation:</strong> Aufruf von <code>research_tool</code>.</li>
|
| 269 |
-
<li><strong>Strukturierungs-Delegation:</strong> Aufruf von <code>recipe_summary_tool</code> (liefert Pydantic-Objekt).</li>
|
| 270 |
-
<li><strong>Visualisierungs-Delegation:</strong> Aufruf von <code>image_generation_tool</code>.</li>
|
| 271 |
-
<li><strong>Meta-Verpackung:</strong> Aufruf von <code>html_packaging_tool</code>.</li>
|
| 272 |
-
</ol>
|
| 273 |
-
|
| 274 |
-
<h3>Fehlerbehandlung mit Routern</h3>
|
| 275 |
-
<p>Falls ein Sub-Agent scheitert (z.B. keine Quellen gefunden), greift Haystacks Kontrollfluss-Logik ein:</p>
|
| 276 |
|
| 277 |
-
<div class="
|
| 278 |
-
<
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
<th>Nutzen im kulinarischen MAS</th>
|
| 284 |
-
</tr>
|
| 285 |
-
</thead>
|
| 286 |
-
<tbody>
|
| 287 |
-
<tr>
|
| 288 |
-
<td><strong>Tool Invocation</strong></td>
|
| 289 |
-
<td><code>ToolInvoker</code></td>
|
| 290 |
-
<td>Führt die geplanten Aktionen (Suche, Bildgen) aus.</td>
|
| 291 |
-
</tr>
|
| 292 |
-
<tr>
|
| 293 |
-
<td><strong>State Management</strong></td>
|
| 294 |
-
<td>Agent State</td>
|
| 295 |
-
<td>Speichert das Rezeptobjekt über Agenten-Grenzen hinweg.</td>
|
| 296 |
-
</tr>
|
| 297 |
-
<tr>
|
| 298 |
-
<td><strong>Exit Conditions</strong></td>
|
| 299 |
-
<td><code>exit_conditions</code></td>
|
| 300 |
-
<td>Beendet den Loop, sobald der finale HTML-Code vorliegt.</td>
|
| 301 |
-
</tr>
|
| 302 |
-
<tr>
|
| 303 |
-
<td><strong>Fehlerkorrektur</strong></td>
|
| 304 |
-
<td><code>ConditionalRouter</code></td>
|
| 305 |
-
<td>Leitet bei Tool-Fehlern den Fluss zurück zur Modifikation (z.B. neuer Such-Prompt).</td>
|
| 306 |
-
</tr>
|
| 307 |
-
</tbody>
|
| 308 |
-
</table>
|
| 309 |
</div>
|
| 310 |
|
| 311 |
-
<div class="mt-8 p-4 bg-slate-100 rounded-lg text-sm text-slate-600 border border-slate-200">
|
| 312 |
-
<strong>Fazit:</strong> Durch die Zerlegung in spezialisierte Pipelines und die Nutzung von Hugging Face Modellen (Qwen, Llama-3, Mistral, FLUX) über Haystack 2.0 entsteht ein robustes, schema-treues System, das den neuen Standard für KI-gestützte Content-Generierung definiert.
|
| 313 |
-
</div>
|
| 314 |
</section>
|
| 315 |
|
| 316 |
-
<footer class="mt-16 pt-8 border-t border-
|
| 317 |
-
<p>
|
| 318 |
</footer>
|
| 319 |
</div>
|
| 320 |
</main>
|
|
@@ -338,8 +384,17 @@ class StableDiffusionGenerator:
|
|
| 338 |
anchor.addEventListener('click', function (e) {
|
| 339 |
e.preventDefault();
|
| 340 |
if(window.innerWidth < 768) {
|
| 341 |
-
sidebar.classList.add('hidden');
|
| 342 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 343 |
document.querySelector(this.getAttribute('href')).scrollIntoView({
|
| 344 |
behavior: 'smooth'
|
| 345 |
});
|
|
@@ -351,7 +406,6 @@ class StableDiffusionGenerator:
|
|
| 351 |
const codeBlock = button.nextElementSibling.querySelector('code');
|
| 352 |
const textToCopy = codeBlock.innerText;
|
| 353 |
|
| 354 |
-
// Clipboard API fallback
|
| 355 |
const textArea = document.createElement("textarea");
|
| 356 |
textArea.value = textToCopy;
|
| 357 |
document.body.appendChild(textArea);
|
|
@@ -360,12 +414,12 @@ class StableDiffusionGenerator:
|
|
| 360 |
try {
|
| 361 |
document.execCommand('copy');
|
| 362 |
const originalText = button.innerText;
|
| 363 |
-
button.innerText = '
|
| 364 |
-
button.classList.add('bg-green-600');
|
| 365 |
|
| 366 |
setTimeout(() => {
|
| 367 |
button.innerText = originalText;
|
| 368 |
-
button.classList.remove('bg-green-600');
|
| 369 |
}, 2000);
|
| 370 |
} catch (err) {
|
| 371 |
console.error('Kopieren fehlgeschlagen', err);
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Konzept eines MAS mit Haystack 2.0</title>
|
| 7 |
|
| 8 |
<!-- Tailwind CSS -->
|
| 9 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 10 |
|
| 11 |
+
<!-- Highlight.js for Code Formatting (Atom One Dark is close to HF's dark code blocks) -->
|
| 12 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
|
| 13 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
| 14 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/python.min.js"></script>
|
| 15 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/xml.min.js"></script>
|
| 16 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/bash.min.js"></script>
|
| 17 |
|
| 18 |
+
<!-- Google Fonts (Inter & Source Code Pro for HF feel) -->
|
| 19 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Source+Code+Pro:wght@400;500&display=swap" rel="stylesheet">
|
| 20 |
|
| 21 |
<script>
|
| 22 |
tailwind.config = {
|
| 23 |
theme: {
|
| 24 |
extend: {
|
| 25 |
fontFamily: {
|
| 26 |
+
sans: ['Inter', 'ui-sans-serif', 'system-ui', 'sans-serif'],
|
| 27 |
+
mono: ['Source Code Pro', 'ui-monospace', 'SFMono-Regular', 'monospace'],
|
| 28 |
},
|
| 29 |
colors: {
|
| 30 |
+
hfYellow: {
|
| 31 |
+
DEFAULT: '#FFD21E',
|
| 32 |
+
hover: '#F5C518',
|
| 33 |
+
light: '#FFF5CC'
|
| 34 |
+
},
|
| 35 |
+
hfGray: {
|
| 36 |
+
50: '#F9FAFB',
|
| 37 |
+
100: '#F3F4F6',
|
| 38 |
+
200: '#E5E7EB',
|
| 39 |
+
800: '#1F2937',
|
| 40 |
+
900: '#111827'
|
| 41 |
+
}
|
| 42 |
}
|
| 43 |
}
|
| 44 |
}
|
|
|
|
| 46 |
</script>
|
| 47 |
|
| 48 |
<style>
|
| 49 |
+
body { font-family: 'Inter', sans-serif; background-color: #ffffff; color: #111827; }
|
| 50 |
+
pre code { font-family: 'Source Code Pro', monospace; border-radius: 0.75rem; font-size: 0.875rem; padding: 1.25rem; }
|
| 51 |
+
.prose h2 { margin-top: 3rem; 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; }
|
| 52 |
+
.prose h3 { margin-top: 2rem; margin-bottom: 1rem; font-weight: 600; font-size: 1.25rem; color: #374151; }
|
| 53 |
+
.prose p { margin-bottom: 1.25rem; line-height: 1.8; color: #4B5563; }
|
| 54 |
+
.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); }
|
| 55 |
+
.prose th, .prose td { border: 1px solid #E5E7EB; padding: 1rem; text-align: left; font-size: 0.95rem; }
|
| 56 |
+
.prose th { background-color: #F9FAFB; font-weight: 600; color: #111827; }
|
| 57 |
+
|
| 58 |
+
/* Tooltip / Copy Button */
|
| 59 |
+
.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; }
|
| 60 |
+
.copy-btn:hover { background: rgba(255,255,255,0.2); color: #fff; }
|
| 61 |
+
.code-wrapper { position: relative; margin-bottom: 2rem; border-radius: 0.75rem; background: #282c34; }
|
| 62 |
+
.file-label { position: absolute; top: -12px; left: 16px; background: #FFD21E; color: #111827; padding: 0.1rem 0.75rem; border-radius: 9999px; font-size: 0.75rem; font-weight: 600; z-index: 10; font-family: 'Source Code Pro', monospace; border: 2px solid #fff; }
|
| 63 |
+
|
| 64 |
+
/* Custom Scrollbar for Sidebar */
|
| 65 |
+
#sidebar::-webkit-scrollbar { width: 6px; }
|
| 66 |
+
#sidebar::-webkit-scrollbar-track { background: transparent; }
|
| 67 |
+
#sidebar::-webkit-scrollbar-thumb { background-color: #E5E7EB; border-radius: 20px; }
|
| 68 |
</style>
|
| 69 |
</head>
|
| 70 |
+
<body class="flex flex-col md:flex-row min-h-screen selection:bg-hfYellow selection:text-black">
|
| 71 |
|
| 72 |
<!-- Mobile Header -->
|
| 73 |
+
<div class="md:hidden bg-white border-b border-gray-200 p-4 flex justify-between items-center sticky top-0 z-50">
|
| 74 |
+
<div class="flex items-center gap-2">
|
| 75 |
+
<span class="text-2xl">🤗</span>
|
| 76 |
+
<h1 class="font-bold text-lg text-gray-900">MAS Konzept</h1>
|
| 77 |
+
</div>
|
| 78 |
+
<button id="mobile-menu-btn" class="text-gray-600 focus:outline-none hover:bg-gray-100 p-2 rounded-lg">
|
| 79 |
<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>
|
| 80 |
</button>
|
| 81 |
</div>
|
| 82 |
|
| 83 |
<!-- Sidebar Navigation -->
|
| 84 |
+
<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">
|
| 85 |
+
<div class="p-6 hidden md:flex flex-col gap-2">
|
| 86 |
+
<div class="flex items-center gap-3">
|
| 87 |
+
<span class="text-3xl">🤗</span>
|
| 88 |
+
<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>
|
| 89 |
+
</div>
|
| 90 |
+
</div>
|
| 91 |
+
|
| 92 |
+
<div class="px-4 pb-4">
|
| 93 |
+
<div class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2 ml-3 mt-4">Architektur</div>
|
| 94 |
+
<ul class="space-y-1 text-sm font-medium">
|
| 95 |
+
<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>
|
| 96 |
+
<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>
|
| 97 |
+
</ul>
|
| 98 |
+
|
| 99 |
+
<div class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2 ml-3 mt-6">Die Agenten (Pipelines)</div>
|
| 100 |
+
<ul class="space-y-1 text-sm font-medium">
|
| 101 |
+
<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>
|
| 102 |
+
<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>
|
| 103 |
+
<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>
|
| 104 |
+
<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>
|
| 105 |
+
</ul>
|
| 106 |
+
|
| 107 |
+
<div class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2 ml-3 mt-6">Orchestrierung & Code</div>
|
| 108 |
+
<ul class="space-y-1 text-sm font-medium">
|
| 109 |
+
<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>
|
| 110 |
+
<li><a href="#repo" class="flex items-center gap-2 py-2 px-3 bg-hfYellow/20 text-yellow-800 rounded-lg hover:bg-hfYellow/30 transition">
|
| 111 |
+
<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="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path></svg>
|
| 112 |
+
8. Repositorystruktur & main.py
|
| 113 |
+
</a></li>
|
| 114 |
+
</ul>
|
| 115 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
</nav>
|
| 117 |
|
| 118 |
<!-- Main Content -->
|
| 119 |
+
<main class="flex-1 w-full max-w-4xl mx-auto p-6 md:p-10 lg:p-14">
|
| 120 |
<div class="prose max-w-none">
|
| 121 |
|
| 122 |
<!-- Hero -->
|
| 123 |
+
<div class="bg-hfYellow/10 border border-hfYellow rounded-2xl p-8 mb-12 shadow-sm">
|
| 124 |
+
<div class="flex items-center gap-3 mb-4">
|
| 125 |
+
<span class="text-4xl">🥘</span>
|
| 126 |
+
<h1 class="text-3xl font-bold text-gray-900 m-0">Architektur eines Kulinarischen MAS</h1>
|
| 127 |
+
</div>
|
| 128 |
+
<p class="text-gray-700 text-lg leading-relaxed m-0">Ein Konzept zur Orchestrierung von Multi-Agenten-Systemen (MAS) für <strong>"The Infinite Cookbook"</strong>. Wir zerlegen komplexe Aufgaben in spezialisierte Haystack 2.0 Pipelines und verbinden sie über die Hugging Face Infrastruktur (Open-Source LLMs) zu einem autonomen System.</p>
|
| 129 |
</div>
|
| 130 |
|
| 131 |
<section id="intro">
|
| 132 |
+
<h2><span>🏗️</span> 1. Das Konzept: Haystack 2.0</h2>
|
| 133 |
+
<p>Der Paradigmenwechsel: Ein einzelnes LLM scheitert oft an komplexen, mehrstufigen Aufgaben. Unser Konzept setzt auf <strong>Komponenten und Pipelines als dynamische Rechengraphen</strong>. Ein Agent in diesem Ökosystem ist eine autonome Einheit (z.B. ein spezialisiertes LLM + Tools), die Aufgaben plant, Werkzeuge auswählt und Strategien anpasst.</p>
|
|
|
|
| 134 |
</section>
|
| 135 |
|
| 136 |
<section id="hf-infra">
|
| 137 |
+
<h2><span>🤗</span> 2. Hugging Face Inference Provider</h2>
|
| 138 |
+
<p>Anstatt auf proprietäre Blackbox-Modelle zu setzen, nutzt dieses Konzept den Hugging Face Hub. Die <code>HuggingFaceAPIChatGenerator</code>-Komponente von Haystack ermöglicht nahtloses Wechseln zwischen Providern:</p>
|
| 139 |
|
| 140 |
<div class="overflow-x-auto">
|
| 141 |
<table>
|
| 142 |
<thead>
|
| 143 |
<tr>
|
| 144 |
+
<th>Infrastruktur</th>
|
| 145 |
<th>Charakteristika</th>
|
| 146 |
+
<th>Modell-Beispiel im MAS</th>
|
| 147 |
</tr>
|
| 148 |
</thead>
|
| 149 |
<tbody>
|
| 150 |
<tr>
|
| 151 |
+
<td><strong>Serverless API</strong></td>
|
| 152 |
+
<td>Kostenlos, für Prototyping</td>
|
| 153 |
+
<td class="font-mono text-sm">Qwen/Qwen2.5-72B-Instruct</td>
|
| 154 |
</tr>
|
| 155 |
<tr>
|
| 156 |
<td><strong>Inference Endpoints</strong></td>
|
| 157 |
+
<td>Dediziert, garantierte Latenz</td>
|
| 158 |
+
<td class="font-mono text-sm">black-forest-labs/FLUX.1-schnell</td>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
</tr>
|
| 160 |
<tr>
|
| 161 |
+
<td><strong>TGI (Text Generation)</strong></td>
|
| 162 |
+
<td>Unterstützt JSON-Guiding</td>
|
| 163 |
+
<td class="font-mono text-sm">mistralai/Mistral-7B-Instruct</td>
|
| 164 |
</tr>
|
| 165 |
</tbody>
|
| 166 |
</table>
|
|
|
|
| 168 |
</section>
|
| 169 |
|
| 170 |
<section id="agent1">
|
| 171 |
+
<h2><span>🔍</span> 3. Agent 1: Forschung & Suche</h2>
|
| 172 |
+
<p>Dieser Sub-Agent kapselt die Recherche. Er nutzt Web-Suchen, lädt HTML-Inhalte herunter, bereinigt sie und rankt sie. Das Ergebnis ist eine fokussierte Wissensbasis.</p>
|
| 173 |
+
<div class="code-wrapper mt-4">
|
| 174 |
+
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
|
|
|
|
| 175 |
<pre><code class="language-python">from haystack import Pipeline
|
| 176 |
from haystack.components.websearch import SerperDevWebSearch
|
| 177 |
+
# ... imports
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
research_pipe = Pipeline()
|
| 179 |
+
research_pipe.add_component("search", SerperDevWebSearch(api_key="KEY"))
|
| 180 |
+
research_pipe.add_component("ranker", TransformersSimilarityRanker())
|
| 181 |
+
# ... verbindungen</code></pre>
|
| 182 |
+
</div>
|
| 183 |
+
</section>
|
| 184 |
+
|
| 185 |
+
<section id="agent2">
|
| 186 |
+
<h2><span>📋</span> 4. Agent 2: Struktur & Pydantic</h2>
|
| 187 |
+
<p>Um die unstrukturierten Forschungsnotizen maschinenlesbar zu machen, zwingen wir das LLM mittels <strong>Pydantic</strong> in ein striktes JSON-Schema. Das eliminiert Halluzinationen in der Datenstruktur.</p>
|
| 188 |
+
</section>
|
| 189 |
|
| 190 |
+
<section id="agent3">
|
| 191 |
+
<h2><span>🎨</span> 5. Agent 3: Visionär (Bildgen.)</h2>
|
| 192 |
+
<p>Da Sprachmodelle keine Bilder malen können, bauen wir eine eigene Custom Component in Haystack (<code>@component</code>), die via <code>diffusers</code> Bibliothek ein Stable Diffusion oder FLUX Modell ansteuert und als Base64-String zurückgibt.</p>
|
| 193 |
+
</section>
|
|
|
|
| 194 |
|
| 195 |
+
<section id="agent4">
|
| 196 |
+
<h2><span>💻</span> 6. Agent 4: Meta-Aggregator (HTML)</h2>
|
| 197 |
+
<p>Dieser Agent nutzt Jinja2-Templates, um die JSON-Daten (aus Agent 2) und den Base64-Bild-String (aus Agent 3) in eine fertige HTML-Rezeptkarte zu gießen.</p>
|
| 198 |
+
</section>
|
| 199 |
|
| 200 |
+
<section id="orchestration">
|
| 201 |
+
<h2><span>🚦</span> 7. Orchestrierung: Agent-as-a-Tool</h2>
|
| 202 |
+
<p>Die Magie passiert im Koordinator-Agenten. Anstatt alle Pipelines händisch zu verketten, packen wir jede Pipeline in ein Haystack <code>Tool</code>-Objekt. Ein übergeordnetes LLM entscheidet dann dynamisch, welches Tool aufgerufen werden muss.</p>
|
|
|
|
| 203 |
</section>
|
| 204 |
|
| 205 |
+
<!-- KAPITEL 8: REPOSITORY UND CODE -->
|
| 206 |
+
<section id="repo">
|
| 207 |
+
<h2 class="bg-hfYellow/20 -mx-6 px-6 py-4 rounded-xl text-yellow-900 border-l-4 border-hfYellow">
|
| 208 |
+
<span>📁</span> 8. Die Code-Struktur (Vom Konzept zur Realität)
|
| 209 |
+
</h2>
|
| 210 |
+
<p>Ein Monolith (alles in einem Skript) führt bei MAS unweigerlich ins Chaos. Eine saubere Repository-Struktur spiegelt die Modularität des Konzepts wider. Hier siehst du, wie die konkreten Dateien in einem echten Projekt aussehen.</p>
|
| 211 |
|
| 212 |
+
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4 mb-8 font-mono text-sm text-gray-700 leading-relaxed shadow-sm">
|
| 213 |
+
infinite-cookbook/<br>
|
| 214 |
+
├── <span class="font-bold text-gray-900">schemas/</span><br>
|
| 215 |
+
│ └── <a href="#file-schema" class="text-blue-600 hover:underline">recipe.py</a> <span class="text-gray-400 italic"># Pydantic Modelle</span><br>
|
| 216 |
+
├── <span class="font-bold text-gray-900">agents/</span><br>
|
| 217 |
+
│ └── <a href="#file-researcher" class="text-blue-600 hover:underline">researcher.py</a> <span class="text-gray-400 italic"># Pipeline Definitionen</span><br>
|
| 218 |
+
├── <span class="font-bold text-gray-900">tools/</span><br>
|
| 219 |
+
│ └── <a href="#file-tools" class="text-blue-600 hover:underline">agent_tools.py</a> <span class="text-gray-400 italic"># Wrapper: Pipeline -> Tool</span><br>
|
| 220 |
+
└── <a href="#file-main" class="text-blue-600 hover:underline font-bold">main.py</a> <span class="text-gray-400 italic"># Orchestrierungs-Loop</span>
|
| 221 |
+
</div>
|
| 222 |
+
|
| 223 |
+
<h3 id="file-schema" class="flex items-center gap-2 mt-10"><svg class="w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"></path></svg> 1. Datenschemata</h3>
|
| 224 |
+
<p>Wir definieren zentral, wie unser Endprodukt auszusehen hat.</p>
|
| 225 |
+
<div class="code-wrapper mt-4">
|
| 226 |
+
<div class="file-label">schemas/recipe.py</div>
|
| 227 |
+
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
|
| 228 |
<pre><code class="language-python">from pydantic import BaseModel
|
| 229 |
+
from typing import List, Literal
|
| 230 |
|
|
|
|
| 231 |
class Ingredient(BaseModel):
|
| 232 |
name: str
|
| 233 |
amount: float
|
|
|
|
| 238 |
servings: int
|
| 239 |
ingredients: List[Ingredient]
|
| 240 |
instructions: List[str]
|
| 241 |
+
difficulty: Literal["Einfach", "Mittel", "Schwer"]</code></pre>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 242 |
</div>
|
|
|
|
|
|
|
| 243 |
|
| 244 |
+
<h3 id="file-researcher" class="flex items-center gap-2 mt-10"><svg class="w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"></path></svg> 2. Pipeline Module</h3>
|
| 245 |
+
<p>Anstatt Pipelines global zu instanziieren, verpacken wir sie in Funktionen (Factory-Pattern). So bleiben sie testbar.</p>
|
| 246 |
+
<div class="code-wrapper mt-4">
|
| 247 |
+
<div class="file-label">agents/researcher.py</div>
|
| 248 |
+
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
|
| 249 |
+
<pre><code class="language-python">from haystack import Pipeline
|
| 250 |
+
from haystack.components.websearch import SerperDevWebSearch
|
| 251 |
+
from haystack.components.fetchers import LinkContentFetcher
|
| 252 |
+
from haystack.components.converters import HTMLToDocument
|
| 253 |
+
|
| 254 |
+
def build_research_pipeline() -> Pipeline:
|
| 255 |
+
"""Baut den Graphen für die Web-Recherche."""
|
| 256 |
+
pipe = Pipeline()
|
| 257 |
+
|
| 258 |
+
# Komponenten hinzufügen
|
| 259 |
+
pipe.add_component("search", SerperDevWebSearch())
|
| 260 |
+
pipe.add_component("fetcher", LinkContentFetcher())
|
| 261 |
+
pipe.add_component("html_converter", HTMLToDocument())
|
| 262 |
+
|
| 263 |
+
# Kanten (Edges) verbinden
|
| 264 |
+
pipe.connect("search.links", "fetcher.urls")
|
| 265 |
+
pipe.connect("fetcher.streams", "html_converter.sources")
|
| 266 |
+
|
| 267 |
+
return pipe</code></pre>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
</div>
|
|
|
|
| 269 |
|
| 270 |
+
<h3 id="file-tools" class="flex items-center gap-2 mt-10"><svg class="w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg> 3. Die Werkzeugkiste (Tool-Wrapper)</h3>
|
| 271 |
+
<p>Hier importieren wir die Pipelines und machen sie für das Koordinator-LLM "lesbar", indem wir sie mit Beschreibungen und Schemata versehen.</p>
|
| 272 |
+
<div class="code-wrapper mt-4">
|
| 273 |
+
<div class="file-label">tools/agent_tools.py</div>
|
| 274 |
+
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
|
| 275 |
+
<pre><code class="language-python">from haystack.tools import Tool
|
| 276 |
+
from agents.researcher import build_research_pipeline
|
| 277 |
+
# from agents.structurer import build_structuring_pipeline
|
| 278 |
+
|
| 279 |
+
# 1. Pipelines instanziieren
|
| 280 |
+
research_pipe = build_research_pipeline()
|
| 281 |
+
# structurer_pipe = build_structuring_pipeline()
|
| 282 |
+
|
| 283 |
+
# 2. In Tools kapseln
|
| 284 |
+
research_tool = Tool(
|
| 285 |
+
name="research_tool",
|
| 286 |
+
description="Nutze dieses Tool ZUERST. Durchsucht das Web nach authentischen Rezept-Infos.",
|
| 287 |
+
parameters={
|
| 288 |
+
"type": "object",
|
| 289 |
+
"properties": {
|
| 290 |
+
"query": {"type": "string", "description": "Der Suchbegriff, z.B. 'original Pad Thai'"}
|
| 291 |
+
},
|
| 292 |
+
"required": ["query"]
|
| 293 |
+
},
|
| 294 |
+
function=research_pipe.run
|
| 295 |
+
)
|
| 296 |
+
|
| 297 |
+
# Tool-Liste für den Haupt-Agenten exportieren
|
| 298 |
+
cookbook_tools = [research_tool] # + structurer_tool, image_tool, html_tool</code></pre>
|
| 299 |
+
</div>
|
| 300 |
+
|
| 301 |
+
<h3 id="file-main" class="flex items-center gap-2 mt-10"><svg class="w-5 h-5 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> 4. Das Herzstück: main.py</h3>
|
| 302 |
+
<p>Die <code>main.py</code> ist nun unglaublich aufgeräumt. Sie initialisiert lediglich das Haupt-LLM (über Hugging Face), importiert die fertige Werkzeugkiste und startet die Interaktions-Schleife.</p>
|
| 303 |
+
<div class="code-wrapper mt-4">
|
| 304 |
+
<div class="file-label">main.py</div>
|
| 305 |
+
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
|
| 306 |
+
<pre><code class="language-python">import os
|
| 307 |
+
from haystack import Pipeline
|
| 308 |
+
from haystack.components.generators.chat import HuggingFaceAPIChatGenerator
|
| 309 |
+
from haystack.components.tools import ToolInvoker
|
| 310 |
+
from haystack.dataclasses import ChatMessage
|
| 311 |
+
|
| 312 |
+
# Unsere sauberen, modularen Imports!
|
| 313 |
+
from tools.agent_tools import cookbook_tools
|
| 314 |
+
|
| 315 |
+
def main():
|
| 316 |
+
# 1. Der Koordinator: Ein starkes Modell, das Tool-Calling beherrscht
|
| 317 |
+
llm = HuggingFaceAPIChatGenerator(
|
| 318 |
+
api_type="serverless_inference_api",
|
| 319 |
+
model="Qwen/Qwen2.5-72B-Instruct",
|
| 320 |
+
tools=cookbook_tools
|
| 321 |
+
)
|
| 322 |
|
| 323 |
+
# 2. Der Invoker: Führt die vom LLM gewählten Tools aus
|
| 324 |
+
invoker = ToolInvoker(tools=cookbook_tools)
|
| 325 |
+
|
| 326 |
+
# 3. Der Routing-Graph
|
| 327 |
+
coordinator = Pipeline()
|
| 328 |
+
coordinator.add_component("llm", llm)
|
| 329 |
+
coordinator.add_component("invoker", invoker)
|
| 330 |
|
| 331 |
+
# Zyklische Verbindung für iteratives Arbeiten
|
| 332 |
+
coordinator.connect("llm.replies", "invoker.messages")
|
| 333 |
+
coordinator.connect("invoker.tool_messages", "llm.messages")
|
| 334 |
+
|
| 335 |
+
# 4. System Start
|
| 336 |
+
user_prompt = "Erstelle ein Rezept für ein thailändisches grünes Curry samt HTML und Bild."
|
| 337 |
+
messages = [ChatMessage.from_user(user_prompt)]
|
| 338 |
|
| 339 |
+
print(f"🤖 Koordinator startet Aufgabe: {user_prompt}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 340 |
|
| 341 |
+
# Run Loop (Vereinfachte Ausführung)
|
| 342 |
+
result = coordinator.run({"llm": {"messages": messages}})
|
| 343 |
+
|
| 344 |
+
# Im echten MAS läuft dies in einer Schleife (ConditionalRouter),
|
| 345 |
+
# bis das LLM entscheidet: "Ich bin fertig und nutze kein Tool mehr."
|
| 346 |
+
print("Fertiges Ergebnis:", result["llm"]["replies"][0].text)
|
|
|
|
|
|
|
|
|
|
| 347 |
|
| 348 |
+
if __name__ == "__main__":
|
| 349 |
+
main()</code></pre>
|
| 350 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 351 |
|
| 352 |
+
<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">
|
| 353 |
+
<span class="text-2xl">💡</span>
|
| 354 |
+
<div>
|
| 355 |
+
<strong class="text-gray-900 block mb-1">Die Architektur-Philosophie:</strong>
|
| 356 |
+
Diese Aufteilung erlaubt es dir, die <code>researcher.py</code> komplett umzuschreiben oder das Modell in <code>main.py</code> auszutauschen, ohne dass du Angst haben musst, den Code des Bild-Generators kaputtzumachen. Das ist die wahre Stärke von Haystack 2.0 in Kombination mit einem modularen Setup!
|
| 357 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 358 |
</div>
|
| 359 |
|
|
|
|
|
|
|
|
|
|
| 360 |
</section>
|
| 361 |
|
| 362 |
+
<footer class="mt-16 pt-8 border-t border-gray-200 text-sm text-gray-400 text-center">
|
| 363 |
+
<p>Ein konzeptioneller Guide für Multi-Agenten-Systeme.<br>Technologie-Stack: Haystack 2.0 & Hugging Face.</p>
|
| 364 |
</footer>
|
| 365 |
</div>
|
| 366 |
</main>
|
|
|
|
| 384 |
anchor.addEventListener('click', function (e) {
|
| 385 |
e.preventDefault();
|
| 386 |
if(window.innerWidth < 768) {
|
| 387 |
+
sidebar.classList.add('hidden');
|
| 388 |
}
|
| 389 |
+
|
| 390 |
+
// Active State Styling Update
|
| 391 |
+
document.querySelectorAll('#sidebar a').forEach(a => {
|
| 392 |
+
a.classList.remove('bg-hfYellow/20', 'text-yellow-800', 'font-semibold');
|
| 393 |
+
a.classList.add('text-gray-600');
|
| 394 |
+
});
|
| 395 |
+
this.classList.remove('text-gray-600');
|
| 396 |
+
this.classList.add('bg-hfYellow/20', 'text-yellow-800', 'font-semibold');
|
| 397 |
+
|
| 398 |
document.querySelector(this.getAttribute('href')).scrollIntoView({
|
| 399 |
behavior: 'smooth'
|
| 400 |
});
|
|
|
|
| 406 |
const codeBlock = button.nextElementSibling.querySelector('code');
|
| 407 |
const textToCopy = codeBlock.innerText;
|
| 408 |
|
|
|
|
| 409 |
const textArea = document.createElement("textarea");
|
| 410 |
textArea.value = textToCopy;
|
| 411 |
document.body.appendChild(textArea);
|
|
|
|
| 414 |
try {
|
| 415 |
document.execCommand('copy');
|
| 416 |
const originalText = button.innerText;
|
| 417 |
+
button.innerText = 'Copied!';
|
| 418 |
+
button.classList.add('bg-green-600', 'text-white', 'border-green-600');
|
| 419 |
|
| 420 |
setTimeout(() => {
|
| 421 |
button.innerText = originalText;
|
| 422 |
+
button.classList.remove('bg-green-600', 'text-white', 'border-green-600');
|
| 423 |
}, 2000);
|
| 424 |
} catch (err) {
|
| 425 |
console.error('Kopieren fehlgeschlagen', err);
|