feat: OpenAI and Anthropic wire-format adapters via new api input
New optional input api: ollama|openai|anthropic (default ollama — existing flows unchanged). - openai: OpenAI Chat Completions format (/v1/chat/completions), Bearer auth — targets vLLM and compatible self-hosted servers. - anthropic: Messages API (/v1/messages), x-api-key + anthropic-version headers, top-level system field, mandatory max_tokens (fixed 4096). - Audit outputs unchanged: model_endpoint/model_name always set; model_digest stays Ollama-only (no digest API on openai/anthropic, field is left empty rather than fabricated). - api_key is only ever placed in auth headers; never in outputs, errors, or audit events (verified against the event log). - No streaming, no tool calls. Bump module + capability version to 0.2.0. Wire-format unit tests for request serialization and response parsing against fixed JSON fixtures; live smoke green on the ollama path and on the openai path against an OpenAI-compatible local endpoint. Signed-off-by: flemming-it <sf@flemming.it>
This commit is contained in:
parent
b5389fce45
commit
305ab1cecd
9 changed files with 662 additions and 136 deletions
80
MODULE.de.md
80
MODULE.de.md
|
|
@ -1,23 +1,35 @@
|
|||
# llm.chat
|
||||
|
||||
Generischer Ollama-kompatibler LLM-Chat-Adapter. Das
|
||||
Baustein-Modul für jeden Flow, der eine LLM-Einzelantwort
|
||||
braucht — klassifizieren, Felder extrahieren, umformulieren,
|
||||
entscheiden — ohne einen eigenen HTTP-Client zu bauen.
|
||||
Generischer LLM-Chat-Adapter. Das Baustein-Modul für jeden
|
||||
Flow, der eine LLM-Einzelantwort braucht — klassifizieren,
|
||||
Felder extrahieren, umformulieren, entscheiden — ohne einen
|
||||
eigenen HTTP-Client zu bauen. Spricht drei Wire-Formate,
|
||||
wählbar über die optionale Eingabe `api`: Ollama (Default),
|
||||
OpenAI Chat Completions (OpenAI, vLLM, kompatible Server) und
|
||||
die Anthropic Messages API.
|
||||
|
||||
## Capability
|
||||
|
||||
- `llm.chat@0.1.0`
|
||||
- `llm.chat@0.2.0`
|
||||
|
||||
## Eingaben
|
||||
|
||||
| Name | Typ | Beschreibung |
|
||||
| ---------------- | ---- | ------------------------------------------------------------------------- |
|
||||
| `prompt` | text | Der User-Prompt. |
|
||||
| `endpoint` | text | Ollama-förmiger `/api/chat`-URL (z.B. `http://localhost:11434/api/chat`). |
|
||||
| `model` | text | Modell-ID (z.B. `qwen2.5:14b`, `llama3.1:8b`). |
|
||||
| `api_key` | text | Optionaler Bearer-Token für Cloud-Endpunkte. |
|
||||
| `endpoint` | text | Chat-Endpunkt-URL passend zur gewählten `api` (siehe unten). |
|
||||
| `model` | text | Modell-ID (z. B. `qwen2.5:14b`, `claude-fable-5`). |
|
||||
| `api_key` | text | Optionaler API-Key. Erscheint nie in Ausgaben, Logs oder Events. |
|
||||
| `system_prompt` | text | Optionale System-Nachricht. Leer = Default des Modells. |
|
||||
| `api` | text | Optionales Wire-Format: `ollama` (Default), `openai`, `anthropic`. |
|
||||
|
||||
### Wire-Formate (`api`)
|
||||
|
||||
| `api` | Endpunkt-Form | Auth-Header | Hinweise |
|
||||
| ----------- | ----------------------------------------- | ---------------------------------- | ------------------------------------------------------------ |
|
||||
| `ollama` | `http://localhost:11434/api/chat` | `Authorization: Bearer` (optional) | Verhalten wie v0.1.0, unverändert. Modell-Digest-Probe via `/api/show`. |
|
||||
| `openai` | `https://.../v1/chat/completions` | `Authorization: Bearer` | OpenAI-Chat-Completions-Format — sprechen auch vLLM und die meisten selbst gehosteten Inferenz-Server. |
|
||||
| `anthropic` | `https://api.anthropic.com/v1/messages` | `x-api-key` + `anthropic-version` | Messages API: `system` ist Top-Level-Feld; `max_tokens` ist Pflicht und steht fest auf 4096. |
|
||||
|
||||
## Ausgaben
|
||||
|
||||
|
|
@ -26,7 +38,7 @@ entscheiden — ohne einen eigenen HTTP-Client zu bauen.
|
|||
| `response` | text | Die Antwort des Assistants als Plain-Text. |
|
||||
| `model_endpoint` | text | URL, gegen die die Antwort erzeugt wurde. |
|
||||
| `model_name` | text | Modell-ID wie an die LLM-API gesendet. |
|
||||
| `model_digest` | text | SHA-256-Digest des bedienenden Ollama-Modells. Leer bei Cloud-APIs. |
|
||||
| `model_digest` | text | SHA-256-Digest des bedienenden Ollama-Modells. Leer bei `openai`/`anthropic` — diese APIs bieten keinen Digest; das Feld bleibt leer statt erfunden. |
|
||||
|
||||
Zusammen beantworten die drei `model_*`-Ausgaben die Audit-
|
||||
Frage: „Welches genaue Modell hat diese Antwort erzeugt?" —
|
||||
|
|
@ -43,8 +55,8 @@ permissions:
|
|||
- "net: api.anthropic.com"
|
||||
```
|
||||
|
||||
Loopback (lokales Ollama) per Default. Cloud-Endpunkte brauchen
|
||||
einen Operator-Policy-Override in
|
||||
Loopback (lokales Ollama / vLLM) per Default. Cloud-Endpunkte
|
||||
brauchen einen Operator-Policy-Override in
|
||||
`~/.chain/config.yaml#security.max_permissions`.
|
||||
|
||||
## Warum dieses Modul statt Inline-HTTP
|
||||
|
|
@ -61,23 +73,24 @@ Drei Gründe:
|
|||
`net:`-Liste. Ein hausgemachtes HTTP-Modul würde seine
|
||||
Endpunkte entweder verstecken oder bei jeder Installation
|
||||
eine frische Review-Oberfläche schaffen.
|
||||
3. **Endpunkt-Portabilität.** Endpunkt + Modell sind Flow-
|
||||
Inputs, keine Compile-Time-Konstanten. Derselbe Flow läuft
|
||||
in der Entwicklung gegen `localhost:11434` und in Produktion
|
||||
gegen ein Inferenz-Cluster — nur die Eingabe wechselt.
|
||||
3. **Endpunkt-Portabilität.** Endpunkt, Modell und Wire-Format
|
||||
sind Flow-Inputs, keine Compile-Time-Konstanten. Derselbe
|
||||
Flow läuft in der Entwicklung gegen `localhost:11434` und
|
||||
in Produktion gegen ein vLLM-Cluster — nur die Eingaben
|
||||
wechseln.
|
||||
|
||||
## Grenzen in v0.1.0
|
||||
## Grenzen in v0.2.0
|
||||
|
||||
- Kein Streaming. Die ganze Antwort wird gepuffert, bevor der
|
||||
Output-Step feuert.
|
||||
- Keine Tool-Call- / Function-Call-Oberfläche. Ein Flow, der
|
||||
Tool-Use braucht, kombiniert mehrere `llm.chat`-Schritte mit
|
||||
Prompt-Engineering oder nutzt MCP via Bridge.
|
||||
- Cloud-Provider-Adapter für OpenAI und Anthropic kommen erst,
|
||||
wenn ein Flow sie braucht. Heute ist das Ollama-Wire-Format
|
||||
das einzige Ziel.
|
||||
- Anthropic-`max_tokens` steht fest auf 4096 (die API verlangt
|
||||
das Feld; eine konfigurierbare Eingabe kommt, sobald ein
|
||||
Flow sie braucht).
|
||||
|
||||
## Beispiel-Flow
|
||||
## Beispiel-Flows
|
||||
|
||||
```yaml
|
||||
name: classify-incoming
|
||||
|
|
@ -98,6 +111,33 @@ outputs:
|
|||
audit_model: $classify.model_digest
|
||||
```
|
||||
|
||||
Gegen einen vLLM-Server (OpenAI-kompatibel):
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- id: classify
|
||||
use: llm.chat@^0
|
||||
with:
|
||||
api: "openai"
|
||||
endpoint: "http://inference.internal:8000/v1/chat/completions"
|
||||
model: "meta-llama/Llama-3.1-8B-Instruct"
|
||||
prompt: $inputs.text
|
||||
```
|
||||
|
||||
Gegen die Anthropic Messages API:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- id: classify
|
||||
use: llm.chat@^0
|
||||
with:
|
||||
api: "anthropic"
|
||||
endpoint: "https://api.anthropic.com/v1/messages"
|
||||
model: "claude-fable-5"
|
||||
api_key: $inputs.anthropic_key
|
||||
prompt: $inputs.text
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue