# 2026-05-17 — Using OpenAI-compatible providers with Dynamo-NTS

**Spec:** `__agent/feature-requests/FR-005-oai-compat-docs.md` (workspace root)
**Scope:** docs-only, LOW priority. Semmilyen TS-változás. NEM kell npm publish.

---

## Mire jó

A Dynamo-NTS OAI service-ek — `DyNTS_OAI_LLM_ServiceBase`, `DyNTS_OAI_LLMChat_ServiceBase`, `DyNTS_OAI_Embedding_ControlService` — az `openai` npm SDK-t használják, és **out-of-the-box bármely OpenAI-API-kompatibilis endpoint-tal működnek** a `baseURL` override-on keresztül. Ez **MÁR MŰKÖDIK** (zéró kód-változás kell), csak eddig nem volt dokumentálva.

A `baseURL` mező a `@futdevpro/fsm-dynamo/ai/open-ai` package `DyFM_OAI_ClientOptions` interface-en él. Bővebben a fsm-dynamo-szintű részletekért: [`@futdevpro/fsm-dynamo/__documentations/2026-05-17-oai-compatible-providers-howto.md`](../../dynamo-fsm/__documentations/2026-05-17-oai-compatible-providers-howto.md).

Tipikus use-case-ek:
- **Lokál fejlesztés** OpenAI-credits nélkül (LM Studio, Ollama)
- **Self-hosted production** infrastruktúra (vLLM, LocalAI klaszter)
- **Cost control** — nyílt-súlyú modellek drága cloud API helyett

---

## A pattern

```typescript
import { DyFM_OAI_Settings, DyFM_OAI_CallSettings } from '@futdevpro/fsm-dynamo/ai/open-ai';
import { DyNTS_OAI_LLMChat_ServiceBase } from '@futdevpro/nts-dynamo/ai/open-ai';

const settings: DyFM_OAI_Settings = new DyFM_OAI_Settings({
  config: {
    baseURL: 'http://<provider-host>:<port>/v1',
    apiKey: '<placeholder-or-real>',
  },
  defaultSettings: new DyFM_OAI_CallSettings({
    useModel: '<provider-specific-model-id>',
  }),
});

class MyChat extends DyNTS_OAI_LLMChat_ServiceBase {}
const chat: MyChat = new MyChat(settings);
```

Csak `config.baseURL` + `config.apiKey` + `defaultSettings.useModel` kell. A többi (organization, project) lokál providereknél figyelmen kívül marad.

A `DyNTS_OAI_Embedding_ControlService` és más OAI alapú service-ek ugyanezt a `DyFM_OAI_Settings`-t fogadják — egy konfig, minden service.

---

## Provider-specifikus minták

### LM Studio (port 1234)

Desktop GUI (Mac/Windows/Linux), beépített OAI-compat szerverrel. Lépések:
1. Töltsd be a modellt a UI-ben (pl. embedding-hez `nomic-embed-text-v1.5`, chat-hez `llama-3.2-3b-instruct`)
2. **Local Server** tab → **Start Server**

```typescript
const lmStudio: DyFM_OAI_Settings = new DyFM_OAI_Settings({
  config: {
    baseURL: 'http://localhost:1234/v1',
    apiKey: 'lm-studio',  // bármilyen non-empty placeholder
  },
  defaultSettings: new DyFM_OAI_CallSettings({
    useModel: 'nomic-embed-text-v1.5',  // ahogy a Local Server tab megjeleníti
  }),
});

// Embedding-hez
class Knowledge_DataService extends DyNTS_OAI_VectorDataService<Knowledge> {
  constructor() { super(/* args */); }
}
```

### Ollama (port 11434, OAI-compat layer ≥ v0.1.14)

CLI-driven, multi-modell runner.

```bash
ollama pull llama3.2:3b
ollama pull nomic-embed-text
ollama serve
```

```typescript
const ollama: DyFM_OAI_Settings = new DyFM_OAI_Settings({
  config: {
    baseURL: 'http://localhost:11434/v1',
    apiKey: 'ollama',  // szintén placeholder
  },
  defaultSettings: new DyFM_OAI_CallSettings({
    useModel: 'nomic-embed-text',  // `ollama list` mutatja
  }),
});
```

### vLLM (port 8000, production GPU)

Python-alapú batched + PagedAttention inference. OAI-compat REST endpoint beépítve.

```bash
pip install vllm
python -m vllm.entrypoints.openai.api_server \
  --model meta-llama/Meta-Llama-3-8B-Instruct \
  --port 8000 \
  --api-key local-secret-token
```

```typescript
const vllm: DyFM_OAI_Settings = new DyFM_OAI_Settings({
  config: {
    baseURL: 'http://gpu-server:8000/v1',
    apiKey: process.env.VLLM_API_KEY ?? 'local-secret-token',
  },
  defaultSettings: new DyFM_OAI_CallSettings({
    useModel: 'meta-llama/Meta-Llama-3-8B-Instruct',  // a `--model` érték
  }),
});
```

### LocalAI (port 8080, REST multi-model)

Go-alapú, multi-backend (llama.cpp + whisper.cpp + stable-diffusion).

```bash
docker run -p 8080:8080 \
  -v $PWD/models:/build/models \
  localai/localai:latest
```

```typescript
const localai: DyFM_OAI_Settings = new DyFM_OAI_Settings({
  config: {
    baseURL: 'http://localai:8080/v1',
    apiKey: 'sk-local',  // placeholder
  },
  defaultSettings: new DyFM_OAI_CallSettings({
    useModel: 'gpt-4',  // LocalAI alias — `models.yaml`-ban mapped
  }),
});
```

---

## Dev → cloud quick recipe

```typescript
const isDev: boolean = process.env.NODE_ENV === 'development';

export const aiSettings: DyFM_OAI_Settings = new DyFM_OAI_Settings({
  config: isDev
    ? {
        baseURL: 'http://localhost:11434/v1',  // Ollama lokálban
        apiKey: 'dev',
      }
    : {
        apiKey: process.env.OPENAI_API_KEY,
        organization: process.env.OPENAI_ORG_ID,
      },
  defaultSettings: new DyFM_OAI_CallSettings({
    useModel: isDev ? 'llama3.2:3b' : 'gpt-4o',
  }),
});

// Az összes Dynamo-NTS OAI service ugyanazt a settings-t fogyasztja:
class ProdChat extends DyNTS_OAI_LLMChat_ServiceBase {}
const chat: ProdChat = new ProdChat(aiSettings);
```

---

## Caveats — service-szintű

### Tool/function calling
A `DyNTS_OAI_LLMChat_ServiceBase` tool-calling support csak akkor működik a lokál provider-eknél, ha:
- **Ollama**: tool-aware modell (Llama-3.1+, Mistral újabb verziók)
- **vLLM**: v0.6+ + megfelelő chat-template
- **LM Studio**: model-függő, gyakran részleges
- **LocalAI**: function-call backend kell konfigolni

Production OpenAI-mintával írt service-ek **lokál providerre váltáskor** előbb tesztelni kell, hogy a tool-callok valóban triggerelnek-e.

### Streaming chat
A `DyNTS_OAI_LLMChat_ServiceBase` streaming (SSE) működik mindenhol, **de**:
- Ollama < v0.1.20 streaming-stabilitás kérdéses
- LocalAI streaming-rate alacsonyabb mint az emit-rate
- vLLM/LM Studio: rendszeresen frissül, érdemes a provider-changelogot követni

### Embedding-modellek
A `DyNTS_OAI_Embedding_ControlService` `useModel`-je a provider-specifikus dedikált embedding modell **pontos ID**-ja:

| Provider | Embedding model ID |
|---|---|
| OpenAI (cloud) | `text-embedding-3-small` / `text-embedding-3-large` |
| LM Studio | `nomic-embed-text-v1.5` / `BAAI/bge-large-en-v1.5` |
| Ollama | `nomic-embed-text` / `mxbai-embed-large` |
| vLLM | csak ha az indítási `--model` embedding-képes (pl. `intfloat/e5-mistral-7b-instruct`) |
| LocalAI | `text-embedding-ada-002` alias (vagy egyéb a `models.yaml`-ban) |

### Context window / max-tokens
A `DyFM_OAI_CallSettings.maxTokens` provider-szintű limit alá kell esnie, különben 400/422 jön vissza:

| Provider | Default context-window | Override |
|---|---|---|
| OpenAI gpt-4o | 128K | API tier |
| LM Studio | a betöltött modell native context | UI slider |
| Ollama | **2048 (legacy default!)** | `OLLAMA_NUM_CTX` env / Modelfile `PARAMETER num_ctx` |
| vLLM | a modell native context | `--max-model-len` flag |
| LocalAI | `models.yaml` `context_size` | per-model konfig |

### Error-handling
- OpenAI cloud: standard 4xx/5xx + structured error body
- Lokál providerek: 404 a modell-name-re (rossz ID), timeout első call-on (modell load), OOM vLLM-en
- Ollama-specifikus: ha a modell még nem `pull`-olt, csendben várakozik a pull-ig — látszólag hang

---

## Reference

| Fájl | Mit ad |
|---|---|
| `fsm-dynamo/.../oai-client-options.interface.ts` | `DyFM_OAI_ClientOptions.baseURL` — a kapcsoló mező |
| `fsm-dynamo/.../oai-settings.control-model.ts` | `DyFM_OAI_Settings` — settings wrapper |
| `dynamo-nts/.../oai-llm.service-base.ts` | `DyNTS_OAI_LLM_ServiceBase` — base LLM client (`openai` SDK instantiation) |
| `dynamo-nts/.../oai-llm-chat.service-base.ts` | `DyNTS_OAI_LLMChat_ServiceBase` — chat service |
| `dynamo-nts/.../oai-embedding.control-service.ts` | `DyNTS_OAI_Embedding_ControlService` — embedding service |

További (fsm-szintű) részletek, ugyanezzel a 4 provider-mintázattal: [`dynamo-fsm/__documentations/2026-05-17-oai-compatible-providers-howto.md`](../../dynamo-fsm/__documentations/2026-05-17-oai-compatible-providers-howto.md).

## Backward compatibility

Docs-only. `baseURL` mindig is létezett az OpenAI SDK-ban, a Dynamo-NTS csak átadja a config-ot (`oai-llm.service-base.ts:91-98`). Ez a doc csak tisztázza a használati mintázatot — semmilyen TS-változás nincs.
