Die Schnittstelle des Labors. Läuft auf eigener Hardware der Enjyn Gruppe, keine Weitergabe an Dritte.
Die Schnittstelle spricht das Format von OpenAI. Wer schon eine Anbindung an ChatGPT hat, ändert Adresse und Schlüssel und ist fertig — alles andere bleibt, wie es ist.
Adresse: https://lab.locsrv.de/v1
Schlüssel: steht im Labor unter Konto, beginnt mit lab_. Er gehört auf deinen Server, nie in eine Webseite, ein Repository oder eine Adresszeile.
| Weg | Art | Wozu |
|---|---|---|
/v1/chat/completions | POST | Fragen stellen, mit oder ohne laufende Ausgabe |
/v1/models | GET | Verfügbare Modelle auflisten |
/health | GET | Zustand, freie Plätze, Warteschlange — ohne Schlüssel |
| Kennung | Läuft auf | Stärke | Kontext |
|---|---|---|---|
locsrv-auto | beide Knoten | das Labor wählt selbst, je nach Frage und Länge | bis 131.072 |
gpt-oss-120b | Node 01 | allgemeine Fragen, Texte, Dokumente | 65.536 |
qwen3-coder-next | Node 02 | Technik, Quelltext, lange Vorlagen | 131.072 |
Ohne Angabe von model entscheidet das Labor selbst. Das ist der empfohlene Weg: Technische Fragen und sehr lange Eingaben gehen dann automatisch auf den passenden Knoten.
curl https://lab.locsrv.de/v1/chat/completions \
-H "Authorization: Bearer $LOCSRV_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "locsrv-auto",
"messages": [
{"role": "system", "content": "Antworte knapp und auf Deutsch."},
{"role": "user", "content": "Was ist ein Werkvertrag?"}
]
}'// Serverseitig ausführen, niemals im Browser: der Schlüssel darf nicht zum Besucher.
const antwort = await fetch('https://lab.locsrv.de/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LOCSRV_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'locsrv-auto',
messages: [{ role: 'user', content: 'Was ist ein Werkvertrag?' }],
}),
});
const daten = await antwort.json();
console.log(daten.choices[0].message.content);<?php
// Developed by Enjyn Gruppe — https://enjyn.de
$ch = curl_init('https://lab.locsrv.de/v1/chat/completions');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_TIMEOUT => 300,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('LOCSRV_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'model' => 'locsrv-auto',
'messages' => [['role' => 'user', 'content' => 'Was ist ein Werkvertrag?']],
], JSON_UNESCAPED_UNICODE),
]);
$antwort = json_decode(curl_exec($ch), true);
echo $antwort['choices'][0]['message']['content'] ?? 'Keine Antwort erhalten.';# Mit dem offiziellen OpenAI-Paket, nur Adresse und Schlüssel tauschen.
from openai import OpenAI
kunde = OpenAI(base_url="https://lab.locsrv.de/v1", api_key=os.environ["LOCSRV_KEY"])
antwort = kunde.chat.completions.create(
model="locsrv-auto",
messages=[{"role": "user", "content": "Was ist ein Werkvertrag?"}],
)
print(antwort.choices[0].message.content)Mit "stream": true kommt die Antwort Stück für Stück als text/event-stream, im selben Format wie bei OpenAI. Das letzte Ereignis ist data: [DONE].
curl -N https://lab.locsrv.de/v1/chat/completions \
-H "Authorization: Bearer $LOCSRV_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"locsrv-auto","stream":true,
"messages":[{"role":"user","content":"Zähle von eins bis zehn."}]}'
Das Labor hat sechs Plätze: vier auf Node 01, zwei auf Node 02. Ein Platz ist eine Anfrage, die gerade gerechnet wird — nicht ein Nutzer und nicht ein offener Chat. Wer tippt oder liest, belegt nichts.
Jeder Zugang hat zusätzlich eine eigene Obergrenze. Sie gilt für den Schlüssel, nicht für die Menschen dahinter: Bedienst du mit einem Schlüssel zehn Besucher, teilen sich diese zehn die Grenze dieses Schlüssels.
| Lage | Antwort | Was zu tun ist |
|---|---|---|
| Platz frei | sofort | nichts |
| Eigene Grenze erreicht | 429 mit Retry-After: 5 | kurz warten, erneut senden |
| Alle Plätze belegt | die Anfrage wartet | nichts, sie läuft an |
| Warteschlange voll | 429 mit Retry-After: 20 | später erneut versuchen |
Mit "stream": true meldet das Labor eine Wartelage sofort, noch bevor das Modell anfängt. Das erste Ereignis trägt dann zusätzlich x_warteschlange mit der Position:
data: {"id":"chatcmpl-…","object":"chat.completion.chunk",
"x_warteschlange": 2,
"choices":[{"index":0,"delta":{},"finish_reason":null}]}
Gewöhnliche Clients überlesen das Zusatzfeld, eigene können daraus „Du bist auf Platz 2" anzeigen. Ohne Streaming gibt es diese Meldung nicht — dort bleibt die Verbindung einfach offen, bis gerechnet wird. Für Chats auf einer Webseite ist Streaming deshalb der bessere Weg.
Den aktuellen Zustand liefert /health ohne Schlüssel:
curl https://lab.locsrv.de/health
{"status":"ok","nodes":2,"plaetze_frei":6,"plaetze_gesamt":6,"warteschlange":0}
{
"id": "chatcmpl-…",
"object": "chat.completion",
"model": "gpt-oss-120b",
"choices": [
{ "index": 0, "finish_reason": "stop",
"message": { "role": "assistant", "content": "Ein Werkvertrag …" } }
],
"usage": { "prompt_tokens": 42, "completion_tokens": 118, "total_tokens": 160 }
}
Das Feld model nennt den Knoten, der tatsächlich geantwortet hat — bei locsrv-auto siehst du daran, wohin die Anfrage gelaufen ist. Die Angaben unter usage sind geschätzt, nicht exakt gezählt.
| Code | Bedeutung | Was zu tun ist |
|---|---|---|
401 | Schlüssel fehlt, ist falsch oder gesperrt | Schlüssel im Labor unter Konto prüfen |
400 | Keine Nachrichten übergeben | messages mitschicken |
429 | Eigene Grenze erreicht oder Warteschlange voll | Retry-After beachten und erneut senden |
503 | Kein Knoten verfügbar | /health prüfen |
Was du wissen solltest, bevor du das produktiv einbaust:
Das Labor rät nicht, wenn es nachsehen kann. Je nach Frage greift es in dieser Reihenfolge:
| Wenn die Frage … | dann … |
|---|---|
eine Adresse enthält, auch ohne https:// | wird genau diese Seite geholt und gelesen |
einen Paragraphen nennt, etwa § 622 BGB oder Art. 5 GG | wird der Gesetzestext direkt bei gesetze-im-internet.de geholt |
| nach einem Begriff fragt („Was ist ein Werkvertrag?") | wird der Artikel aus der deutschen Wikipedia gelesen |
| nach Aktuellem, Preisen oder Zahlen fragt | läuft die eigene Metasuche, die besten drei Treffer werden im Volltext gelesen |
| dem Modell trotzdem Angaben fehlen | fordert es selbst eine Suche an, und die Frage wird erneut gestellt |
Alles Nachgeschlagene steht mit Quellenangabe in der Antwort. Rechenaufgaben und Fragen zum Wetter lösen bewusst kein Nachschlagen aus.
Über die Schnittstelle gehen derzeit nur Texte. Bilder und PDFs wertet das Labor in der Weboberfläche aus: Dort liest ein eigenes Bildmodell das Bild, bei PDFs kommt Texterkennung dazu. Eine Schnittstelle dafür kommt, wenn der Bedarf da ist.